1 /*********************************************************************
3 * File : $Source: /cvsroot/ijbswa/current/wolfssl.c,v $
5 * Purpose : File with TLS/SSL extension. Contains methods for
6 * creating, using and closing TLS/SSL connections
9 * Copyright : Copyright (C) 2018-2021 by Fabian Keil <fk@fabiankeil.de>
10 * Copyright (C) 2020 Maxim Antonov <mantonov@gmail.com>
11 * Copyright (C) 2017 Vaclav Svec. FIT CVUT.
13 * This program is free software; you can redistribute it
14 * and/or modify it under the terms of the GNU General
15 * Public License as published by the Free Software
16 * Foundation; either version 2 of the License, or (at
17 * your option) any later version.
19 * This program is distributed in the hope that it will
20 * be useful, but WITHOUT ANY WARRANTY; without even the
21 * implied warranty of MERCHANTABILITY or FITNESS FOR A
22 * PARTICULAR PURPOSE. See the GNU General Public
23 * License for more details.
25 * The GNU General Public License should be included with
26 * this file. If not, you can view it at
27 * http://www.gnu.org/copyleft/gpl.html
28 * or write to the Free Software Foundation, Inc., 59
29 * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31 *********************************************************************/
38 #include <wolfssl/options.h>
39 #include <wolfssl/openssl/x509v3.h>
40 #include <wolfssl/ssl.h>
41 #include <wolfssl/wolfcrypt/coding.h>
42 #include <wolfssl/wolfcrypt/rsa.h>
49 #include "jbsockets.h"
51 #include "ssl_common.h"
53 static int ssl_certificate_is_invalid(const char *cert_file);
54 static int generate_host_certificate(struct client_state *csp,
55 const char *certificate_path, const char *key_path);
56 static void free_client_ssl_structures(struct client_state *csp);
57 static void free_server_ssl_structures(struct client_state *csp);
58 static int ssl_store_cert(struct client_state *csp, X509 *crt);
59 static void log_ssl_errors(int debuglevel, const char* fmt, ...) __attribute__((format(printf, 2, 3)));
61 static int wolfssl_initialized = 0;
64 * Whether or not sharing the RNG is thread-safe
65 * doesn't matter because we only use it with
66 * the certificate_mutex locked.
68 static RNG wolfssl_rng;
70 #ifndef WOLFSSL_ALT_CERT_CHAINS
72 * Without WOLFSSL_ALT_CERT_CHAINS wolfSSL will reject valid
73 * certificates if the certificate chain contains CA certificates
74 * that are "only" signed by trusted CA certificates but aren't
75 * trusted CAs themselves.
77 #warning wolfSSL has been compiled without WOLFSSL_ALT_CERT_CHAINS
80 /*********************************************************************
82 * Function : wolfssl_init
84 * Description : Initializes wolfSSL library once
90 *********************************************************************/
91 static void wolfssl_init(void)
93 if (wolfssl_initialized == 0)
95 privoxy_mutex_lock(&ssl_init_mutex);
96 if (wolfssl_initialized == 0)
98 if (wolfSSL_Init() != WOLFSSL_SUCCESS)
100 log_error(LOG_LEVEL_FATAL, "Failed to initialize wolfSSL");
102 wc_InitRng(&wolfssl_rng);
103 wolfssl_initialized = 1;
105 privoxy_mutex_unlock(&ssl_init_mutex);
110 /*********************************************************************
112 * Function : is_ssl_pending
114 * Description : Tests if there are some waiting data on ssl connection.
115 * Only considers data that has actually been received
116 * locally and ignores data that is still on the fly
117 * or has not yet been sent by the remote end.
120 * 1 : ssl_attr = SSL context to test
122 * Returns : 0 => No data are pending
123 * >0 => Pending data length. XXX: really?
125 *********************************************************************/
126 extern size_t is_ssl_pending(struct ssl_attr *ssl_attr)
128 return (size_t)wolfSSL_pending(ssl_attr->wolfssl_attr.ssl);
132 /*********************************************************************
134 * Function : ssl_send_data
136 * Description : Sends the content of buf (for n bytes) to given SSL
137 * connection context.
140 * 1 : ssl_attr = SSL context to send data to
141 * 2 : buf = Pointer to data to be sent
142 * 3 : len = Length of data to be sent to the SSL context
144 * Returns : Length of sent data or negative value on error.
146 *********************************************************************/
147 extern int ssl_send_data(struct ssl_attr *ssl_attr, const unsigned char *buf, size_t len)
151 int pos = 0; /* Position of unsent part in buffer */
159 ssl = ssl_attr->wolfssl_attr.ssl;
160 fd = wolfSSL_get_fd(ssl);
164 int send_len = (int)len - pos;
166 log_error(LOG_LEVEL_WRITING, "TLS on socket %d: %N",
167 fd, send_len, buf+pos);
169 ret = wolfSSL_write(ssl, buf+pos, send_len);
172 log_ssl_errors(LOG_LEVEL_ERROR,
173 "Sending data on socket %d over TLS failed", fd);
177 /* Adding count of sent bytes to position in buffer */
185 /*********************************************************************
187 * Function : ssl_recv_data
189 * Description : Receives data from given SSL context and puts
193 * 1 : ssl_attr = SSL context to receive data from
194 * 2 : buf = Pointer to buffer where data will be written
195 * 3 : max_length = Maximum number of bytes to read
197 * Returns : Number of bytes read, 0 for EOF, or -1
200 *********************************************************************/
201 extern int ssl_recv_data(struct ssl_attr *ssl_attr, unsigned char *buf, size_t max_length)
207 memset(buf, 0, max_length);
210 * Receiving data from SSL context into buffer
212 ssl = ssl_attr->wolfssl_attr.ssl;
213 ret = wolfSSL_read(ssl, buf, (int)max_length);
214 fd = wolfSSL_get_fd(ssl);
218 log_ssl_errors(LOG_LEVEL_ERROR,
219 "Receiving data on socket %d over TLS failed", fd);
224 log_error(LOG_LEVEL_RECEIVED, "TLS from socket %d: %N",
231 /*********************************************************************
233 * Function : get_public_key_size_string
235 * Description : Translates a public key type to a string.
238 * 1 : key_type = The public key type.
240 * Returns : String containing the translated key size.
242 *********************************************************************/
243 static const char *get_public_key_size_string(int key_type)
248 return "RSA key size";
250 return "DSA key size";
252 return "EC key size";
254 return "non-RSA/DSA/EC key size";
259 /*********************************************************************
261 * Function : ssl_store_cert
263 * Description : This function is called once for each certificate in the
264 * server's certificate trusted chain and prepares
265 * information about the certificate. The information can
266 * be used to inform the user about invalid certificates.
269 * 1 : csp = Current client state (buffers, headers, etc...)
270 * 2 : cert = certificate from trusted chain
272 * Returns : 0 on success and negative value on error
274 *********************************************************************/
275 static int ssl_store_cert(struct client_state *csp, X509 *cert)
278 struct certs_chain *last = &(csp->server_certs_chain);
280 WOLFSSL_BIO *bio = BIO_new(BIO_s_mem());
281 WOLFSSL_EVP_PKEY *pkey = NULL;
282 char *bio_mem_data = NULL;
285 unsigned char serial_number[32];
286 int serial_number_size = sizeof(serial_number);
287 WOLFSSL_X509_NAME *issuer_name;
288 WOLFSSL_X509_NAME *subject_name;
289 char *subject_alternative_name;
291 int san_prefix_printed = 0;
295 log_ssl_errors(LOG_LEVEL_ERROR, "BIO_new() failed");
300 * Searching for last item in certificates linked list
302 while (last->next != NULL)
308 * Preparing next item in linked list for next certificate
310 last->next = zalloc_or_die(sizeof(struct certs_chain));
313 * Saving certificate file into buffer
315 if (wolfSSL_PEM_write_bio_X509(bio, cert) != WOLFSSL_SUCCESS)
317 log_ssl_errors(LOG_LEVEL_ERROR, "wolfSSL_PEM_write_bio_X509() failed");
322 len = wolfSSL_BIO_get_mem_data(bio, &bio_mem_data);
323 last->file_buf = malloc((size_t)len + 1);
324 if (last->file_buf == NULL)
326 log_error(LOG_LEVEL_ERROR,
327 "Failed to allocate %lu bytes to store the X509 PEM certificate",
333 strncpy(last->file_buf, bio_mem_data, (size_t)len);
334 last->file_buf[len] = '\0';
335 wolfSSL_BIO_free(bio);
336 bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem());
339 log_ssl_errors(LOG_LEVEL_ERROR, "wolfSSL_BIO_new() failed");
345 * Saving certificate information into buffer
347 l = wolfSSL_X509_get_version(cert);
348 if (l >= 0 && l <= 2)
350 if (wolfSSL_BIO_printf(bio, "cert. version : %ld\n", l + 1) <= 0)
352 log_ssl_errors(LOG_LEVEL_ERROR,
353 "wolfSSL_BIO_printf() for version failed");
360 if (wolfSSL_BIO_printf(bio, "cert. version : Unknown (%ld)\n", l) <= 0)
362 log_ssl_errors(LOG_LEVEL_ERROR,
363 "wolfSSL_BIO_printf() for version failed");
369 if (wolfSSL_BIO_puts(bio, "serial number : ") <= 0)
371 log_ssl_errors(LOG_LEVEL_ERROR,
372 "wolfSSL_BIO_puts() for serial number failed");
376 if (wolfSSL_X509_get_serial_number(cert, serial_number, &serial_number_size)
379 log_error(LOG_LEVEL_ERROR, "wolfSSL_X509_get_serial_number() failed");
384 if (serial_number_size <= (int)sizeof(char))
386 if (wolfSSL_BIO_printf(bio, "%lu (0x%lx)\n", serial_number[0],
387 serial_number[0]) <= 0)
389 log_ssl_errors(LOG_LEVEL_ERROR,
390 "wolfSSL_BIO_printf() for serial number as single byte failed");
398 for (i = 0; i < serial_number_size; i++)
400 if (wolfSSL_BIO_printf(bio, "%02x%c", serial_number[i],
401 ((i + 1 == serial_number_size) ? '\n' : ':')) <= 0)
403 log_ssl_errors(LOG_LEVEL_ERROR,
404 "wolfSSL_BIO_printf() for serial number bytes failed");
411 if (wolfSSL_BIO_puts(bio, "issuer name : ") <= 0)
413 log_ssl_errors(LOG_LEVEL_ERROR, "wolfSSL_BIO_puts() for issuer failed");
417 issuer_name = wolfSSL_X509_get_issuer_name(cert);
418 if (wolfSSL_X509_NAME_get_sz(issuer_name) <= 0)
420 if (wolfSSL_BIO_puts(bio, "none") <= 0)
422 log_ssl_errors(LOG_LEVEL_ERROR,
423 "wolfSSL_BIO_puts() for issuer name failed");
428 else if (wolfSSL_X509_NAME_print_ex(bio, issuer_name, 0, 0) < 0)
430 log_ssl_errors(LOG_LEVEL_ERROR,
431 "wolfSSL_X509_NAME_print_ex() for issuer failed");
436 if (wolfSSL_BIO_puts(bio, "\nsubject name : ") <= 0)
438 log_ssl_errors(LOG_LEVEL_ERROR,
439 "wolfSSL_BIO_puts() for subject name failed");
443 subject_name = wolfSSL_X509_get_subject_name(cert);
444 if (wolfSSL_X509_NAME_get_sz(subject_name) <= 0)
446 if (wolfSSL_BIO_puts(bio, "none") <= 0)
448 log_ssl_errors(LOG_LEVEL_ERROR,
449 "wolfSSL_BIO_puts() for subject name failed");
454 else if (wolfSSL_X509_NAME_print_ex(bio, subject_name, 0, 0) < 0)
456 log_ssl_errors(LOG_LEVEL_ERROR,
457 "wolfSSL_X509_NAME_print_ex() for subject name failed");
462 if (wolfSSL_BIO_puts(bio, "\nissued on : ") <= 0)
464 log_ssl_errors(LOG_LEVEL_ERROR,
465 "wolfSSL_BIO_puts() for issued on failed");
469 if (!wolfSSL_ASN1_TIME_print(bio, wolfSSL_X509_get_notBefore(cert)))
471 log_ssl_errors(LOG_LEVEL_ERROR,
472 "wolfSSL_ASN1_TIME_print() for issued on failed");
477 if (wolfSSL_BIO_puts(bio, "\nexpires on : ") <= 0)
479 log_ssl_errors(LOG_LEVEL_ERROR,
480 "wolfSSL_BIO_puts() for expires on failed");
484 if (!wolfSSL_ASN1_TIME_print(bio, wolfSSL_X509_get_notAfter(cert)))
486 log_ssl_errors(LOG_LEVEL_ERROR,
487 "wolfSSL_ASN1_TIME_print() for expires on failed");
492 /* XXX: Show signature algorithm */
494 pkey = wolfSSL_X509_get_pubkey(cert);
497 log_ssl_errors(LOG_LEVEL_ERROR, "wolfSSL_X509_get_pubkey() failed");
501 ret = wolfSSL_BIO_printf(bio, "\n%-18s: %d bits",
502 get_public_key_size_string(wolfSSL_EVP_PKEY_base_id(pkey)),
503 wolfSSL_EVP_PKEY_bits(pkey));
506 log_ssl_errors(LOG_LEVEL_ERROR,
507 "wolfSSL_BIO_printf() for key size failed");
513 * XXX: Show cert usage, etc.
515 loc = wolfSSL_X509_get_ext_by_NID(cert, NID_basic_constraints, -1);
518 WOLFSSL_X509_EXTENSION *ex = wolfSSL_X509_get_ext(cert, loc);
519 if (BIO_puts(bio, "\nbasic constraints : ") <= 0)
521 log_ssl_errors(LOG_LEVEL_ERROR,
522 "BIO_printf() for basic constraints failed");
526 if (!wolfSSL_X509V3_EXT_print(bio, ex, 0, 0))
528 if (!wolfSSL_ASN1_STRING_print_ex(bio,
529 wolfSSL_X509_EXTENSION_get_data(ex),
530 ASN1_STRFLGS_RFC2253))
532 log_ssl_errors(LOG_LEVEL_ERROR,
533 "wolfSSL_ASN1_STRING_print_ex() for basic constraints failed");
540 while ((subject_alternative_name = wolfSSL_X509_get_next_altname(cert))
543 if (san_prefix_printed == 0)
545 ret = wolfSSL_BIO_printf(bio, "\nsubject alt name : ");
546 san_prefix_printed = 1;
550 ret = wolfSSL_BIO_printf(bio, "%s ", subject_alternative_name);
554 log_ssl_errors(LOG_LEVEL_ERROR,
555 "wolfSSL_BIO_printf() for Subject Alternative Name failed");
563 * This code compiles but does not work because wolfSSL
564 * sets NID_netscape_cert_type to NID_undef.
566 loc = wolfSSL_X509_get_ext_by_NID(cert, NID_netscape_cert_type, -1);
569 WOLFSSL_X509_EXTENSION *ex = wolfSSL_X509_get_ext(cert, loc);
570 if (wolfSSL_BIO_puts(bio, "\ncert. type : ") <= 0)
572 log_ssl_errors(LOG_LEVEL_ERROR,
573 "wolfSSL_BIO_printf() for cert type failed");
577 if (!wolfSSL_X509V3_EXT_print(bio, ex, 0, 0))
579 if (!wolfSSL_ASN1_STRING_print_ex(bio,
580 wolfSSL_X509_EXTENSION_get_data(ex),
581 ASN1_STRFLGS_RFC2253))
583 log_ssl_errors(LOG_LEVEL_ERROR,
584 "wolfSSL_ASN1_STRING_print_ex() for cert type failed");
594 * This code compiles but does not work. wolfSSL_OBJ_obj2nid()
595 * triggers a 'X509V3_EXT_print not yet implemented for ext type' message.
597 loc = wolfSSL_X509_get_ext_by_NID(cert, NID_key_usage, -1);
600 WOLFSSL_X509_EXTENSION *extension = wolfSSL_X509_get_ext(cert, loc);
601 if (BIO_puts(bio, "\nkey usage : ") <= 0)
603 log_ssl_errors(LOG_LEVEL_ERROR,
604 "wolfSSL_BIO_printf() for key usage failed");
608 if (!wolfSSL_X509V3_EXT_print(bio, extension, 0, 0))
610 if (!wolfSSL_ASN1_STRING_print_ex(bio,
611 wolfSSL_X509_EXTENSION_get_data(extension),
612 ASN1_STRFLGS_RFC2253))
614 log_ssl_errors(LOG_LEVEL_ERROR,
615 "wolfSSL_ASN1_STRING_print_ex() for key usage failed");
625 * This compiles but doesn't work. wolfSSL_X509_ext_isSet_by_NID()
626 * complains about "NID not in table".
628 loc = wolfSSL_X509_get_ext_by_NID(cert, NID_ext_key_usage, -1);
630 WOLFSSL_X509_EXTENSION *ex = wolfSSL_X509_get_ext(cert, loc);
631 if (wolfSSL_BIO_puts(bio, "\next key usage : ") <= 0)
633 log_ssl_errors(LOG_LEVEL_ERROR,
634 "wolfSSL_BIO_printf() for ext key usage failed");
638 if (!wolfSSL_X509V3_EXT_print(bio, ex, 0, 0))
640 if (!wolfSSL_ASN1_STRING_print_ex(bio,
641 wolfSSL_X509_EXTENSION_get_data(ex),
642 ASN1_STRFLGS_RFC2253))
644 log_ssl_errors(LOG_LEVEL_ERROR,
645 "wolfSSL_ASN1_STRING_print_ex() for ext key usage failed");
655 * This compiles but doesn't work. wolfSSL_X509_ext_isSet_by_NID()
656 * complains about "NID not in table". XXX: again?
658 loc = wolfSSL_X509_get_ext_by_NID(cert, NID_certificate_policies, -1);
661 WOLFSSL_X509_EXTENSION *ex = wolfSSL_X509_get_ext(cert, loc);
662 if (wolfSSL_BIO_puts(bio, "\ncertificate policies : ") <= 0)
664 log_ssl_errors(LOG_LEVEL_ERROR,
665 "wolfSSL_BIO_printf() for certificate policies failed");
669 if (!wolfSSL_X509V3_EXT_print(bio, ex, 0, 0))
671 if (!wolfSSL_ASN1_STRING_print_ex(bio,
672 wolfSSL_X509_EXTENSION_get_data(ex),
673 ASN1_STRFLGS_RFC2253))
675 log_ssl_errors(LOG_LEVEL_ERROR,
676 "wolfSSL_ASN1_STRING_print_ex() for certificate policies failed");
684 /* make valgrind happy */
685 static const char zero = 0;
686 wolfSSL_BIO_write(bio, &zero, 1);
688 len = wolfSSL_BIO_get_mem_data(bio, &bio_mem_data);
691 log_error(LOG_LEVEL_ERROR, "BIO_get_mem_data() returned %ld "
692 "while gathering certificate information", len);
696 encoded_text = html_encode(bio_mem_data);
697 if (encoded_text == NULL)
699 log_error(LOG_LEVEL_ERROR,
700 "Failed to HTML-encode the certificate information");
705 strlcpy(last->info_buf, encoded_text, sizeof(last->info_buf));
712 wolfSSL_BIO_free(bio);
716 wolfSSL_EVP_PKEY_free(pkey);
722 /*********************************************************************
724 * Function : host_to_hash
726 * Description : Creates MD5 hash from host name. Host name is loaded
727 * from structure csp and saved again into it.
730 * 1 : csp = Current client state (buffers, headers, etc...)
732 * Returns : -1 => Error while creating hash
733 * 0 => Hash created successfully
735 *********************************************************************/
736 static int host_to_hash(struct client_state *csp)
742 ret = wc_InitMd5(&md5);
748 ret = wc_Md5Update(&md5, (const byte *)csp->http->host,
749 (word32)strlen(csp->http->host));
755 ret = wc_Md5Final(&md5, csp->http->hash_of_host);
763 /* Converting hash into string with hex */
764 for (i = 0; i < 16; i++)
766 ret = snprintf((char *)csp->http->hash_of_host_hex + 2 * i,
767 sizeof(csp->http->hash_of_host_hex) - 2 * i,
768 "%02x", csp->http->hash_of_host[i]);
771 log_error(LOG_LEVEL_ERROR, "sprintf() failed. Return value: %d", ret);
780 /*********************************************************************
782 * Function : create_client_ssl_connection
784 * Description : Creates a TLS-secured connection with the client.
787 * 1 : csp = Current client state (buffers, headers, etc...)
789 * Returns : 0 on success, negative value if connection wasn't created
792 *********************************************************************/
793 extern int create_client_ssl_connection(struct client_state *csp)
795 struct ssl_attr *ssl_attr = &csp->ssl_client_attr;
796 /* Paths to certificates file and key file */
797 char *key_file = NULL;
798 char *cert_file = NULL;
802 /* Should probably be called from somewhere else. */
806 * Preparing hash of host for creating certificates
808 ret = host_to_hash(csp);
811 log_error(LOG_LEVEL_ERROR, "Generating hash of host failed: %d", ret);
817 * Preparing paths to certificates files and key file
819 cert_file = make_certs_path(csp->config->certificate_directory,
820 (const char *)csp->http->hash_of_host_hex, CERT_FILE_TYPE);
821 key_file = make_certs_path(csp->config->certificate_directory,
822 (const char *)csp->http->hash_of_host_hex, KEY_FILE_TYPE);
824 if (cert_file == NULL || key_file == NULL)
830 /* Do we need to generate a new host certificate and key? */
831 if (!file_exists(cert_file) || !file_exists(key_file) ||
832 ssl_certificate_is_invalid(cert_file))
835 * Yes we do. Lock mutex to prevent certificate and
836 * key inconsistencies.
838 privoxy_mutex_lock(&certificate_mutex);
839 ret = generate_host_certificate(csp, cert_file, key_file);
840 privoxy_mutex_unlock(&certificate_mutex);
844 * No need to log something, generate_host_certificate()
851 ssl_attr->wolfssl_attr.ctx = wolfSSL_CTX_new(wolfSSLv23_method());
852 if (ssl_attr->wolfssl_attr.ctx == NULL)
854 log_ssl_errors(LOG_LEVEL_ERROR, "Unable to create TLS context");
859 /* Set the key and cert */
860 if (wolfSSL_CTX_use_certificate_file(ssl_attr->wolfssl_attr.ctx,
861 cert_file, SSL_FILETYPE_PEM) != WOLFSSL_SUCCESS)
863 log_ssl_errors(LOG_LEVEL_ERROR,
864 "Loading host certificate %s failed", cert_file);
869 if (wolfSSL_CTX_use_PrivateKey_file(ssl_attr->wolfssl_attr.ctx,
870 key_file, SSL_FILETYPE_PEM) != WOLFSSL_SUCCESS)
872 log_ssl_errors(LOG_LEVEL_ERROR,
873 "Loading host certificate private key %s failed", key_file);
878 wolfSSL_CTX_set_options(ssl_attr->wolfssl_attr.ctx, WOLFSSL_OP_NO_SSLv3);
880 ssl = ssl_attr->wolfssl_attr.ssl = wolfSSL_new(ssl_attr->wolfssl_attr.ctx);
882 if (wolfSSL_set_fd(ssl, csp->cfd) != WOLFSSL_SUCCESS)
884 log_ssl_errors(LOG_LEVEL_ERROR,
885 "wolfSSL_set_fd() failed to set the client socket");
890 if (csp->config->cipher_list != NULL)
892 if (!wolfSSL_set_cipher_list(ssl, csp->config->cipher_list))
894 log_ssl_errors(LOG_LEVEL_ERROR,
895 "Setting the cipher list '%s' for the client connection failed",
896 csp->config->cipher_list);
903 * Handshake with client
905 log_error(LOG_LEVEL_CONNECT,
906 "Performing the TLS/SSL handshake with client. Hash of host: %s",
907 csp->http->hash_of_host_hex);
909 ret = wolfSSL_accept(ssl);
910 if (ret == WOLFSSL_SUCCESS)
912 log_error(LOG_LEVEL_CONNECT,
913 "Client successfully connected over %s (%s).",
914 wolfSSL_get_version(ssl), wolfSSL_get_cipher_name(ssl));
915 csp->ssl_with_client_is_opened = 1;
921 int error = wolfSSL_get_error(ssl, ret);
922 log_error(LOG_LEVEL_ERROR,
923 "The TLS handshake with the client failed. error = %d, %s",
924 error, wolfSSL_ERR_error_string((unsigned long)error, buffer));
930 * Freeing allocated paths to files
935 /* Freeing structures if connection wasn't created successfully */
938 free_client_ssl_structures(csp);
944 /*********************************************************************
946 * Function : shutdown_connection
948 * Description : Shuts down a TLS connection if the socket is still
952 * 1 : csp = Current client state (buffers, headers, etc...)
956 *********************************************************************/
957 static void shutdown_connection(WOLFSSL *ssl, const char *type)
959 int shutdown_attempts = 0;
962 enum { MAX_SHUTDOWN_ATTEMPTS = 2 };
964 fd = wolfSSL_get_fd(ssl);
968 if (!socket_is_still_alive(fd))
970 log_error(LOG_LEVEL_CONNECT, "Not shutting down %s connection "
971 "on socket %d. The socket is no longer alive.", type, fd);
974 ret = wolfSSL_shutdown(ssl);
975 if (WOLFSSL_SUCCESS != ret)
978 log_error(LOG_LEVEL_CONNECT, "Failed to shutdown %s connection "
979 "on socket %d. Attempts so far: %d, ret: %d", type, fd,
980 shutdown_attempts, ret);
982 } while (ret == WOLFSSL_SHUTDOWN_NOT_DONE &&
983 shutdown_attempts < MAX_SHUTDOWN_ATTEMPTS);
984 if (WOLFSSL_SUCCESS != ret)
987 int error = wolfSSL_get_error(ssl, ret);
988 log_error(LOG_LEVEL_ERROR, "Failed to shutdown %s connection "
989 "on socket %d after %d attempts. ret: %d, error: %d, %s",
990 type, fd, shutdown_attempts, ret, error,
991 wolfSSL_ERR_error_string((unsigned long)error, buffer));
996 /*********************************************************************
998 * Function : close_client_ssl_connection
1000 * Description : Closes TLS connection with client. This function
1001 * checks if this connection is already created.
1004 * 1 : csp = Current client state (buffers, headers, etc...)
1008 *********************************************************************/
1009 extern void close_client_ssl_connection(struct client_state *csp)
1011 struct ssl_attr *ssl_attr = &csp->ssl_client_attr;
1013 if (csp->ssl_with_client_is_opened == 0)
1019 * Notify the peer that the connection is being closed.
1021 shutdown_connection(ssl_attr->wolfssl_attr.ssl, "client");
1023 free_client_ssl_structures(csp);
1024 csp->ssl_with_client_is_opened = 0;
1028 /*********************************************************************
1030 * Function : free_client_ssl_structures
1032 * Description : Frees structures used for SSL communication with
1036 * 1 : csp = Current client state (buffers, headers, etc...)
1040 *********************************************************************/
1041 static void free_client_ssl_structures(struct client_state *csp)
1043 struct ssl_attr *ssl_attr = &csp->ssl_client_attr;
1045 if (ssl_attr->wolfssl_attr.ssl)
1047 wolfSSL_free(ssl_attr->wolfssl_attr.ssl);
1049 if (ssl_attr->wolfssl_attr.ctx)
1051 wolfSSL_CTX_free(ssl_attr->wolfssl_attr.ctx);
1056 /*********************************************************************
1058 * Function : close_server_ssl_connection
1060 * Description : Closes TLS connection with server. This function
1061 * checks if this connection is already opened.
1064 * 1 : csp = Current client state (buffers, headers, etc...)
1068 *********************************************************************/
1069 extern void close_server_ssl_connection(struct client_state *csp)
1071 struct ssl_attr *ssl_attr = &csp->ssl_server_attr;
1073 if (csp->ssl_with_server_is_opened == 0)
1079 * Notify the peer that the connection is being closed.
1081 shutdown_connection(ssl_attr->wolfssl_attr.ssl, "server");
1083 free_server_ssl_structures(csp);
1084 csp->ssl_with_server_is_opened = 0;
1088 /*********************************************************************
1090 * Function : create_server_ssl_connection
1092 * Description : Creates TLS-secured connection with the server.
1095 * 1 : csp = Current client state (buffers, headers, etc...)
1097 * Returns : 0 on success, negative value if connection wasn't created
1100 *********************************************************************/
1101 extern int create_server_ssl_connection(struct client_state *csp)
1103 wolfssl_connection_attr *ssl_attrs = &csp->ssl_server_attr.wolfssl_attr;
1106 int connect_ret = 0;
1108 csp->server_cert_verification_result = SSL_CERT_NOT_VERIFIED;
1109 csp->server_certs_chain.next = NULL;
1111 ssl_attrs->ctx = wolfSSL_CTX_new(wolfSSLv23_method());
1112 if (ssl_attrs->ctx == NULL)
1114 log_ssl_errors(LOG_LEVEL_ERROR, "TLS context creation failed");
1119 if (csp->dont_verify_certificate)
1121 wolfSSL_CTX_set_verify(ssl_attrs->ctx, WOLFSSL_VERIFY_NONE, NULL);
1123 else if (wolfSSL_CTX_load_verify_locations(ssl_attrs->ctx,
1124 csp->config->trusted_cas_file, NULL) != WOLFSSL_SUCCESS)
1126 log_ssl_errors(LOG_LEVEL_ERROR, "Loading trusted CAs file %s failed",
1127 csp->config->trusted_cas_file);
1132 wolfSSL_CTX_set_options(ssl_attrs->ctx, WOLFSSL_OP_NO_SSLv3);
1134 ssl = ssl_attrs->ssl = wolfSSL_new(ssl_attrs->ctx);
1136 if (wolfSSL_set_fd(ssl, csp->server_connection.sfd) != WOLFSSL_SUCCESS)
1138 log_ssl_errors(LOG_LEVEL_ERROR,
1139 "wolfSSL_set_fd() failed to set the server socket");
1144 if (csp->config->cipher_list != NULL)
1146 if (wolfSSL_set_cipher_list(ssl, csp->config->cipher_list) != WOLFSSL_SUCCESS)
1148 log_ssl_errors(LOG_LEVEL_ERROR,
1149 "Setting the cipher list '%s' for the server connection failed",
1150 csp->config->cipher_list);
1156 ret = wolfSSL_UseSNI(ssl, WOLFSSL_SNI_HOST_NAME,
1157 csp->http->host, (unsigned short)strlen(csp->http->host));
1158 if (ret != WOLFSSL_SUCCESS)
1160 log_ssl_errors(LOG_LEVEL_ERROR, "Failed to set use of SNI");
1165 ret = wolfSSL_check_domain_name(ssl, csp->http->host);
1166 if (ret != WOLFSSL_SUCCESS)
1169 int error = wolfSSL_get_error(ssl, ret);
1170 log_error(LOG_LEVEL_FATAL,
1171 "Failed to set check domain name. error = %d, %s",
1172 error, wolfSSL_ERR_error_string((unsigned long)error, buffer));
1177 #ifdef HAVE_SECURE_RENEGOTIATION
1178 #warning wolfssl has been compiled with HAVE_SECURE_RENEGOTIATION while you probably want HAVE_RENEGOTIATION_INDICATION
1179 if(wolfSSL_UseSecureRenegotiation(ssl) != WOLFSSL_SUCCESS)
1181 log_ssl_errors(LOG_LEVEL_ERROR,
1182 "Failed to enable 'Secure' Renegotiation. Continuing anyway.");
1185 #ifndef HAVE_RENEGOTIATION_INDICATION
1186 #warning Looks like wolfssl has been compiled without HAVE_RENEGOTIATION_INDICATION
1189 log_error(LOG_LEVEL_CONNECT,
1190 "Performing the TLS/SSL handshake with the server");
1192 /* wolfSSL_Debugging_ON(); */
1193 connect_ret = wolfSSL_connect(ssl);
1194 /* wolfSSL_Debugging_OFF(); */
1197 wolfSSL_Debugging_ON();
1199 if (!csp->dont_verify_certificate)
1201 long verify_result = wolfSSL_get_error(ssl, connect_ret);
1203 if (verify_result == X509_V_OK)
1206 csp->server_cert_verification_result = SSL_CERT_VALID;
1210 WOLF_STACK_OF(WOLFSSL_X509) *chain;
1212 csp->server_cert_verification_result = verify_result;
1213 log_error(LOG_LEVEL_ERROR,
1214 "X509 certificate verification for %s failed with error %ld: %s",
1215 csp->http->hostport, verify_result,
1216 wolfSSL_X509_verify_cert_error_string(verify_result));
1218 chain = wolfSSL_get_peer_cert_chain(ssl);
1222 for (i = 0; i < wolfSSL_sk_X509_num(chain); i++)
1224 if (ssl_store_cert(csp, wolfSSL_sk_X509_value(chain, i)) != 0)
1226 log_error(LOG_LEVEL_ERROR,
1227 "ssl_store_cert() failed for cert %d", i);
1229 * ssl_send_certificate_error() wil not be able to show
1230 * the certificate but the user will stil get the error
1242 wolfSSL_Debugging_OFF();
1244 if (connect_ret == WOLFSSL_SUCCESS)
1246 log_error(LOG_LEVEL_CONNECT,
1247 "Server successfully connected over %s (%s).",
1248 wolfSSL_get_version(ssl), wolfSSL_get_cipher_name(ssl));
1249 csp->ssl_with_server_is_opened = 1;
1255 int error = wolfSSL_get_error(ssl, ret);
1256 log_error(LOG_LEVEL_ERROR,
1257 "The TLS handshake with the server %s failed. error = %d, %s",
1258 csp->http->hostport,
1259 error, wolfSSL_ERR_error_string((unsigned long)error, buffer));
1264 /* Freeing structures if connection wasn't created successfully */
1267 free_server_ssl_structures(csp);
1274 /*********************************************************************
1276 * Function : free_server_ssl_structures
1278 * Description : Frees structures used for SSL communication with server
1281 * 1 : csp = Current client state (buffers, headers, etc...)
1285 *********************************************************************/
1286 static void free_server_ssl_structures(struct client_state *csp)
1288 struct ssl_attr *ssl_attr = &csp->ssl_server_attr;
1290 if (ssl_attr->wolfssl_attr.ssl)
1292 wolfSSL_free(ssl_attr->wolfssl_attr.ssl);
1294 if (ssl_attr->wolfssl_attr.ctx)
1296 wolfSSL_CTX_free(ssl_attr->wolfssl_attr.ctx);
1301 /*********************************************************************
1303 * Function : log_ssl_errors
1305 * Description : Log SSL errors
1308 * 1 : debuglevel = Debug level
1309 * 2 : desc = Error description
1313 *********************************************************************/
1314 static void log_ssl_errors(int debuglevel, const char* fmt, ...)
1316 unsigned long err_code;
1317 char prefix[ERROR_BUF_SIZE];
1319 va_start(args, fmt);
1320 vsnprintf(prefix, sizeof(prefix), fmt, args);
1323 while ((err_code = wolfSSL_ERR_get_error()))
1325 char err_buf[ERROR_BUF_SIZE];
1327 wolfSSL_ERR_error_string_n(err_code, err_buf, sizeof(err_buf));
1328 log_error(debuglevel, "%s: %s", prefix, err_buf);
1332 * In case if called by mistake and there were
1333 * no TLS errors let's report it to the log.
1337 log_error(debuglevel, "%s: no TLS errors detected", prefix);
1342 /*********************************************************************
1344 * Function : ssl_base64_encode
1346 * Description : Encode a buffer into base64 format.
1349 * 1 : dst = Destination buffer
1350 * 2 : dlen = Destination buffer length
1351 * 3 : olen = Number of bytes written
1352 * 4 : src = Source buffer
1353 * 5 : slen = Amount of data to be encoded
1355 * Returns : 0 on success, error code othervise
1357 *********************************************************************/
1358 extern int ssl_base64_encode(unsigned char *dst, size_t dlen, size_t *olen,
1359 const unsigned char *src, size_t slen)
1361 word32 output_length;
1364 *olen = 4 * ((slen/3) + ((slen%3) ? 1 : 0)) + 1;
1370 output_length = (word32)dlen;
1371 ret = Base64_Encode_NoNl(src, (word32)slen, dst, &output_length);
1374 log_error(LOG_LEVEL_ERROR, "base64 encoding failed with %d", ret);
1377 *olen = output_length;
1384 /*********************************************************************
1386 * Function : close_file_stream
1388 * Description : Close file stream, report error on close error
1391 * 1 : f = file stream to close
1392 * 2 : path = path for error report
1396 *********************************************************************/
1397 static void close_file_stream(FILE *f, const char *path)
1401 log_error(LOG_LEVEL_ERROR,
1402 "Error closing file %s: %s", path, strerror(errno));
1407 /*********************************************************************
1409 * Function : write_certificate
1411 * Description : Writes a PEM-encoded certificate to a file.
1414 * 1 : certificate_path = Path to the file to create
1415 * 2 : certificate = PEM-encoded certificate to write.
1417 * Returns : NULL => Error. Otherwise a key;
1419 *********************************************************************/
1420 static int write_certificate(const char *certificate_path, const char *certificate)
1424 assert(certificate_path != NULL);
1425 assert(certificate != NULL);
1427 fp = fopen(certificate_path, "wb");
1430 log_error(LOG_LEVEL_ERROR,
1431 "Failed to open %s to write the certificate: %E",
1435 if (fputs(certificate, fp) < 0)
1437 log_error(LOG_LEVEL_ERROR, "Failed to write certificate to %s: %E",
1449 /*********************************************************************
1451 * Function : generate_rsa_key
1453 * Description : Generates a new RSA key and saves it in a file.
1456 * 1 : rsa_key_path = Path to the key that should be written.
1458 * Returns : -1 => Error while generating private key
1461 *********************************************************************/
1462 static int generate_rsa_key(const char *rsa_key_path)
1465 byte rsa_key_der[4096];
1472 assert(file_exists(rsa_key_path) != 1);
1474 wc_InitRsaKey(&rsa_key, NULL);
1476 log_error(LOG_LEVEL_CONNECT, "Making RSA key %s ...", rsa_key_path);
1477 ret = wc_MakeRsaKey(&rsa_key, RSA_KEYSIZE, RSA_KEY_PUBLIC_EXPONENT,
1481 log_error(LOG_LEVEL_ERROR, "RSA key generation failed");
1485 log_error(LOG_LEVEL_CONNECT, "Done making RSA key %s", rsa_key_path);
1487 der_key_size = wc_RsaKeyToDer(&rsa_key, rsa_key_der, sizeof(rsa_key_der));
1488 wc_FreeRsaKey(&rsa_key);
1489 if (der_key_size < 0)
1491 log_error(LOG_LEVEL_ERROR, "RSA key conversion to DER format failed");
1495 pem_key_size = wc_DerToPem(rsa_key_der, (word32)der_key_size,
1496 key_pem, sizeof(key_pem), PRIVATEKEY_TYPE);
1497 if (pem_key_size < 0)
1499 log_error(LOG_LEVEL_ERROR, "RSA key conversion to PEM format failed");
1505 * Saving key into file
1507 if ((f = fopen(rsa_key_path, "wb")) == NULL)
1509 log_error(LOG_LEVEL_ERROR,
1510 "Opening file %s to save private key failed: %E",
1516 if (fwrite(key_pem, 1, (size_t)pem_key_size, f) != pem_key_size)
1518 log_error(LOG_LEVEL_ERROR,
1519 "Writing private key into file %s failed",
1521 close_file_stream(f, rsa_key_path);
1526 close_file_stream(f, rsa_key_path);
1535 /*********************************************************************
1537 * Function : ssl_certificate_load
1539 * Description : Loads certificate from file.
1542 * 1 : cert_path = The certificate path to load
1544 * Returns : NULL => error loading certificate,
1545 * pointer to certificate instance otherwise
1547 *********************************************************************/
1548 static X509 *ssl_certificate_load(const char *cert_path)
1551 FILE *cert_f = NULL;
1553 if (!(cert_f = fopen(cert_path, "r")))
1555 log_error(LOG_LEVEL_ERROR,
1556 "Error opening certificate file %s: %s", cert_path, strerror(errno));
1560 if (!(cert = PEM_read_X509(cert_f, NULL, NULL, NULL)))
1562 log_ssl_errors(LOG_LEVEL_ERROR,
1563 "Error reading certificate file %s", cert_path);
1566 close_file_stream(cert_f, cert_path);
1571 /*********************************************************************
1573 * Function : ssl_certificate_is_invalid
1575 * Description : Checks whether or not a certificate is valid.
1576 * Currently only checks that the certificate can be
1577 * parsed and that the "valid to" date is in the future.
1580 * 1 : cert_file = The certificate to check
1582 * Returns : 0 => The certificate is valid.
1583 * 1 => The certificate is invalid
1585 *********************************************************************/
1586 static int ssl_certificate_is_invalid(const char *cert_file)
1592 if (!(cert = ssl_certificate_load(cert_file)))
1597 ret = wolfSSL_X509_cmp_current_time(wolfSSL_X509_get_notAfter(cert));
1600 log_ssl_errors(LOG_LEVEL_ERROR,
1601 "Error checking certificate %s validity", cert_file);
1605 wolfSSL_X509_free(cert);
1607 return ret == -1 ? 1 : 0;
1611 /*********************************************************************
1613 * Function : load_rsa_key
1615 * Description : Load a PEM-encoded RSA file into memory.
1618 * 1 : rsa_key_path = Path to the file that holds the key.
1619 * 2 : password = Password to unlock the key. NULL if no
1620 * password is required.
1621 * 3 : rsa_key = Initialized RSA key storage.
1623 * Returns : 0 => Error while creating the key.
1626 *********************************************************************/
1627 static int load_rsa_key(const char *rsa_key_path, const char *password, RsaKey *rsa_key)
1632 unsigned char *key_pem;
1633 DerBuffer *der_buffer;
1634 word32 der_index = 0;
1635 DerBuffer decrypted_der_buffer;
1636 unsigned char der_data[4096];
1638 fp = fopen(rsa_key_path, "rb");
1641 log_error(LOG_LEVEL_ERROR, "Failed to open %s: %E", rsa_key_path);
1645 /* Get file length */
1646 if (fseek(fp, 0, SEEK_END))
1648 log_error(LOG_LEVEL_ERROR,
1649 "Unexpected error while fseek()ing to the end of %s: %E",
1657 log_error(LOG_LEVEL_ERROR,
1658 "Unexpected ftell() error while loading %s: %E",
1663 length = (size_t)ret;
1665 /* Go back to the beginning. */
1666 if (fseek(fp, 0, SEEK_SET))
1668 log_error(LOG_LEVEL_ERROR,
1669 "Unexpected error while fseek()ing to the beginning of %s: %E",
1675 key_pem = malloc_or_die(length);
1677 if (1 != fread(key_pem, length, 1, fp))
1679 log_error(LOG_LEVEL_ERROR,
1680 "Couldn't completely read file %s.", rsa_key_path);
1688 if (password == NULL)
1690 ret = wc_PemToDer(key_pem, (long)length, PRIVATEKEY_TYPE,
1691 &der_buffer, NULL, NULL, NULL);
1695 der_buffer = &decrypted_der_buffer;
1696 der_buffer->buffer = der_data;
1697 ret = wc_KeyPemToDer(key_pem, (int)length, der_buffer->buffer,
1698 sizeof(der_data), password);
1701 log_error(LOG_LEVEL_ERROR,
1702 "Failed to convert PEM key %s into DER format. Error: %ld",
1707 der_buffer->length = (word32)ret;
1714 log_error(LOG_LEVEL_ERROR,
1715 "Failed to convert buffer into DER format for file %s. Error = %ld",
1720 ret = wc_RsaPrivateKeyDecode(der_buffer->buffer, &der_index, rsa_key,
1721 der_buffer->length);
1722 if (password == NULL)
1728 log_error(LOG_LEVEL_ERROR,
1729 "Failed to decode DER buffer into RSA key structure for %s",
1737 #ifndef WOLFSSL_ALT_NAMES
1738 #error wolfSSL lacks Subject Alternative Name support
1740 /*********************************************************************
1742 * Function : set_subject_alternative_name
1744 * Description : Sets the Subject Alternative Name extension to
1745 * a cert using the awesome "API" provided by wolfSSL.
1748 * 1 : cert = The certificate to modify
1749 * 2 : hostname = The hostname to add
1751 * Returns : <0 => Error.
1754 *********************************************************************/
1755 static int set_subject_alternative_name(struct Cert *certificate, const char *hostname)
1757 const size_t hostname_length = strlen(hostname);
1759 if (hostname_length >= 253)
1762 * We apparently only have a byte to represent the length
1765 log_error(LOG_LEVEL_ERROR,
1766 "Hostname '%s' is too long to set Subject Alternative Name",
1770 certificate->altNames[0] = 0x30; /* Sequence */
1771 certificate->altNames[1] = (unsigned char)hostname_length + 2;
1773 certificate->altNames[2] = 0x82; /* DNS name */
1774 certificate->altNames[3] = (unsigned char)hostname_length;
1775 memcpy(&certificate->altNames[4], hostname, hostname_length);
1777 certificate->altNamesSz = (int)hostname_length + 4;
1783 /*********************************************************************
1785 * Function : generate_host_certificate
1787 * Description : Creates certificate file in presetted directory.
1788 * If certificate already exists, no other certificate
1789 * will be created. Subject of certificate is named
1790 * by csp->http->host from parameter. This function also
1791 * triggers generating of private key for new certificate.
1794 * 1 : csp = Current client state (buffers, headers, etc...)
1795 * 2 : certificate_path = Path to the certficate to generate.
1796 * 3 : rsa_key_path = Path to the key to generate for the
1799 * Returns : -1 => Error while creating certificate.
1800 * 0 => Certificate already exists.
1801 * 1 => Certificate created
1803 *********************************************************************/
1804 static int generate_host_certificate(struct client_state *csp,
1805 const char *certificate_path, const char *rsa_key_path)
1807 struct Cert certificate;
1811 byte certificate_der[4096];
1812 int der_certificate_length;
1813 byte certificate_pem[4096];
1814 int pem_certificate_length;
1816 if (file_exists(certificate_path) == 1)
1818 /* The file exists, but is it valid? */
1819 if (ssl_certificate_is_invalid(certificate_path))
1821 log_error(LOG_LEVEL_CONNECT,
1822 "Certificate %s is no longer valid. Removing it.",
1824 if (unlink(certificate_path))
1826 log_error(LOG_LEVEL_ERROR, "Failed to unlink %s: %E",
1830 if (unlink(rsa_key_path))
1832 log_error(LOG_LEVEL_ERROR, "Failed to unlink %s: %E",
1844 log_error(LOG_LEVEL_CONNECT, "Creating new certificate %s",
1847 if (enforce_sane_certificate_state(certificate_path, rsa_key_path))
1852 wc_InitRsaKey(&rsa_key, NULL);
1853 wc_InitRsaKey(&ca_key, NULL);
1855 if (generate_rsa_key(rsa_key_path) == -1)
1860 wc_InitCert(&certificate);
1862 strncpy(certificate.subject.country, CERT_PARAM_COUNTRY_CODE, CTC_NAME_SIZE);
1863 strncpy(certificate.subject.org, "Privoxy", CTC_NAME_SIZE);
1864 strncpy(certificate.subject.unit, "Development", CTC_NAME_SIZE);
1865 strncpy(certificate.subject.commonName, csp->http->host, CTC_NAME_SIZE);
1866 certificate.daysValid = 90;
1867 certificate.selfSigned = 0;
1868 certificate.sigType = CTC_SHA256wRSA;
1869 if (!host_is_ip_address(csp->http->host) &&
1870 set_subject_alternative_name(&certificate, csp->http->host))
1876 ret = wc_SetIssuer(&certificate, csp->config->ca_cert_file);
1879 log_error(LOG_LEVEL_ERROR,
1880 "Failed to set Issuer file %s", csp->config->ca_cert_file);
1885 if (load_rsa_key(rsa_key_path, NULL, &rsa_key) != 1)
1887 log_error(LOG_LEVEL_ERROR,
1888 "Failed to load RSA key %s", rsa_key_path);
1893 /* wolfSSL_Debugging_ON(); */
1894 der_certificate_length = wc_MakeCert(&certificate, certificate_der,
1895 sizeof(certificate_der), &rsa_key, NULL, &wolfssl_rng);
1896 /* wolfSSL_Debugging_OFF(); */
1898 if (der_certificate_length < 0)
1900 log_error(LOG_LEVEL_ERROR, "Failed to make certificate");
1905 if (load_rsa_key(csp->config->ca_key_file, csp->config->ca_password,
1908 log_error(LOG_LEVEL_ERROR,
1909 "Failed to load CA key %s", csp->config->ca_key_file);
1914 der_certificate_length = wc_SignCert(certificate.bodySz, certificate.sigType,
1915 certificate_der, sizeof(certificate_der), &ca_key, NULL, &wolfssl_rng);
1916 wc_FreeRsaKey(&ca_key);
1917 if (der_certificate_length < 0)
1919 log_error(LOG_LEVEL_ERROR, "Failed to sign certificate");
1924 pem_certificate_length = wc_DerToPem(certificate_der,
1925 (word32)der_certificate_length, certificate_pem,
1926 sizeof(certificate_pem), CERT_TYPE);
1927 if (pem_certificate_length < 0)
1929 log_error(LOG_LEVEL_ERROR,
1930 "Failed to convert certificate from DER to PEM");
1934 certificate_pem[pem_certificate_length] = '\0';
1936 if (write_certificate(certificate_path, (const char*)certificate_pem))
1945 wc_FreeRsaKey(&rsa_key);
1946 wc_FreeRsaKey(&ca_key);
1953 /*********************************************************************
1955 * Function : ssl_crt_verify_info
1957 * Description : Returns an informational string about the verification
1958 * status of a certificate.
1961 * 1 : buf = Buffer to write to
1962 * 2 : size = Maximum size of buffer
1963 * 3 : csp = client state
1967 *********************************************************************/
1968 extern void ssl_crt_verify_info(char *buf, size_t size, struct client_state *csp)
1970 strncpy(buf, wolfSSL_X509_verify_cert_error_string(
1971 csp->server_cert_verification_result), size);
1976 #ifdef FEATURE_GRACEFUL_TERMINATION
1977 /*********************************************************************
1979 * Function : ssl_release
1981 * Description : Release all SSL resources
1987 *********************************************************************/
1988 extern void ssl_release(void)
1990 if (wolfssl_initialized == 1)
1992 wc_FreeRng(&wolfssl_rng);
1996 #endif /* def FEATURE_GRACEFUL_TERMINATION */