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