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