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