1 /** @file
2   SSL/TLS Initialization 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 SPDX-License-Identifier: BSD-2-Clause-Patent
7 
8 **/
9 
10 #include "InternalTlsLib.h"
11 
12 /**
13   Initializes the OpenSSL library.
14 
15   This function registers ciphers and digests used directly and indirectly
16   by SSL/TLS, and initializes the readable error messages.
17   This function must be called before any other action takes places.
18 
19   @retval TRUE   The OpenSSL library has been initialized.
20   @retval FALSE  Failed to initialize the OpenSSL library.
21 
22 **/
23 BOOLEAN
24 EFIAPI
TlsInitialize(VOID)25 TlsInitialize (
26   VOID
27   )
28 {
29   INTN            Ret;
30 
31   //
32   // Performs initialization of crypto and ssl library, and loads required
33   // algorithms.
34   //
35   Ret = OPENSSL_init_ssl (
36           OPENSSL_INIT_LOAD_SSL_STRINGS | OPENSSL_INIT_LOAD_CRYPTO_STRINGS,
37           NULL
38           );
39   if (Ret != 1) {
40     return FALSE;
41   }
42 
43   //
44   // Initialize the pseudorandom number generator.
45   //
46   return RandomSeed (NULL, 0);
47 }
48 
49 /**
50   Free an allocated SSL_CTX object.
51 
52   @param[in]  TlsCtx    Pointer to the SSL_CTX object to be released.
53 
54 **/
55 VOID
56 EFIAPI
TlsCtxFree(IN VOID * TlsCtx)57 TlsCtxFree (
58   IN   VOID                  *TlsCtx
59   )
60 {
61   if (TlsCtx == NULL) {
62     return;
63   }
64 
65   if (TlsCtx != NULL) {
66     SSL_CTX_free ((SSL_CTX *) (TlsCtx));
67   }
68 }
69 
70 /**
71   Creates a new SSL_CTX object as framework to establish TLS/SSL enabled
72   connections.
73 
74   @param[in]  MajorVer    Major Version of TLS/SSL Protocol.
75   @param[in]  MinorVer    Minor Version of TLS/SSL Protocol.
76 
77   @return  Pointer to an allocated SSL_CTX object.
78            If the creation failed, TlsCtxNew() returns NULL.
79 
80 **/
81 VOID *
82 EFIAPI
TlsCtxNew(IN UINT8 MajorVer,IN UINT8 MinorVer)83 TlsCtxNew (
84   IN     UINT8                    MajorVer,
85   IN     UINT8                    MinorVer
86   )
87 {
88   SSL_CTX  *TlsCtx;
89   UINT16   ProtoVersion;
90 
91   ProtoVersion = (MajorVer << 8) | MinorVer;
92 
93   TlsCtx = SSL_CTX_new (SSLv23_client_method ());
94   if (TlsCtx == NULL) {
95     return NULL;
96   }
97 
98   //
99   // Ensure SSLv3 is disabled
100   //
101   SSL_CTX_set_options (TlsCtx, SSL_OP_NO_SSLv3);
102 
103   //
104   // Treat as minimum accepted versions by setting the minimal bound.
105   // Client can use higher TLS version if server supports it
106   //
107   SSL_CTX_set_min_proto_version (TlsCtx, ProtoVersion);
108 
109   return (VOID *) TlsCtx;
110 }
111 
112 /**
113   Free an allocated TLS object.
114 
115   This function removes the TLS object pointed to by Tls and frees up the
116   allocated memory. If Tls is NULL, nothing is done.
117 
118   @param[in]  Tls    Pointer to the TLS object to be freed.
119 
120 **/
121 VOID
122 EFIAPI
TlsFree(IN VOID * Tls)123 TlsFree (
124   IN     VOID                     *Tls
125   )
126 {
127   TLS_CONNECTION  *TlsConn;
128 
129   TlsConn = (TLS_CONNECTION *) Tls;
130   if (TlsConn == NULL) {
131     return;
132   }
133 
134   //
135   // Free the internal TLS and related BIO objects.
136   //
137   if (TlsConn->Ssl != NULL) {
138     SSL_free (TlsConn->Ssl);
139   }
140 
141   OPENSSL_free (Tls);
142 }
143 
144 /**
145   Create a new TLS object for a connection.
146 
147   This function creates a new TLS object for a connection. The new object
148   inherits the setting of the underlying context TlsCtx: connection method,
149   options, verification setting.
150 
151   @param[in]  TlsCtx    Pointer to the SSL_CTX object.
152 
153   @return  Pointer to an allocated SSL object.
154            If the creation failed, TlsNew() returns NULL.
155 
156 **/
157 VOID *
158 EFIAPI
TlsNew(IN VOID * TlsCtx)159 TlsNew (
160   IN     VOID                     *TlsCtx
161   )
162 {
163   TLS_CONNECTION  *TlsConn;
164   SSL_CTX         *SslCtx;
165   X509_STORE      *X509Store;
166 
167   TlsConn = NULL;
168 
169   //
170   // Allocate one new TLS_CONNECTION object
171   //
172   TlsConn = (TLS_CONNECTION *) OPENSSL_malloc (sizeof (TLS_CONNECTION));
173   if (TlsConn == NULL) {
174     return NULL;
175   }
176 
177   TlsConn->Ssl = NULL;
178 
179   //
180   // Create a new SSL Object
181   //
182   TlsConn->Ssl = SSL_new ((SSL_CTX *) TlsCtx);
183   if (TlsConn->Ssl == NULL) {
184     TlsFree ((VOID *) TlsConn);
185     return NULL;
186   }
187 
188   //
189   // This retains compatibility with previous version of OpenSSL.
190   //
191   SSL_set_security_level (TlsConn->Ssl, 0);
192 
193   //
194   // Initialize the created SSL Object
195   //
196   SSL_set_info_callback (TlsConn->Ssl, NULL);
197 
198   TlsConn->InBio = NULL;
199 
200   //
201   // Set up Reading BIO for TLS connection
202   //
203   TlsConn->InBio = BIO_new (BIO_s_mem ());
204   if (TlsConn->InBio == NULL) {
205     TlsFree ((VOID *) TlsConn);
206     return NULL;
207   }
208 
209   //
210   // Sets the behaviour of memory BIO when it is empty. It will set the
211   // read retry flag.
212   //
213   BIO_set_mem_eof_return (TlsConn->InBio, -1);
214 
215   TlsConn->OutBio = NULL;
216 
217   //
218   // Set up Writing BIO for TLS connection
219   //
220   TlsConn->OutBio = BIO_new (BIO_s_mem ());
221   if (TlsConn->OutBio == NULL) {
222     TlsFree ((VOID *) TlsConn);
223     return NULL;
224   }
225 
226   //
227   // Sets the behaviour of memory BIO when it is empty. It will set the
228   // write retry flag.
229   //
230   BIO_set_mem_eof_return (TlsConn->OutBio, -1);
231 
232   ASSERT (TlsConn->Ssl != NULL && TlsConn->InBio != NULL && TlsConn->OutBio != NULL);
233 
234   //
235   // Connects the InBio and OutBio for the read and write operations.
236   //
237   SSL_set_bio (TlsConn->Ssl, TlsConn->InBio, TlsConn->OutBio);
238 
239   //
240   // Create new X509 store if needed
241   //
242   SslCtx    = SSL_get_SSL_CTX (TlsConn->Ssl);
243   X509Store = SSL_CTX_get_cert_store (SslCtx);
244   if (X509Store == NULL) {
245     X509Store = X509_STORE_new ();
246     if (X509Store == NULL) {
247       TlsFree ((VOID *) TlsConn);
248       return NULL;
249     }
250     SSL_CTX_set1_verify_cert_store (SslCtx, X509Store);
251     X509_STORE_free (X509Store);
252   }
253 
254   //
255   // Set X509_STORE flags used in certificate validation
256   //
257   X509_STORE_set_flags (
258     X509Store,
259     X509_V_FLAG_PARTIAL_CHAIN | X509_V_FLAG_NO_CHECK_TIME
260     );
261   return (VOID *) TlsConn;
262 }
263 
264