From 122d9dd3ffa48f4f9297b9b05cb36f9ebcf7b7e6 Mon Sep 17 00:00:00 2001 From: rdb Date: Sat, 24 Dec 2016 22:19:51 +0100 Subject: [PATCH] Support building with OpenSSL 1.1.0 --- dtool/src/prc/encryptStreamBuf.cxx | 88 ++++++++++++++++++----------- dtool/src/prc/encryptStreamBuf.h | 6 +- panda/src/downloader/httpClient.cxx | 18 +++--- 3 files changed, 67 insertions(+), 45 deletions(-) diff --git a/dtool/src/prc/encryptStreamBuf.cxx b/dtool/src/prc/encryptStreamBuf.cxx index acf76f9c0a..fed8b8e7b6 100644 --- a/dtool/src/prc/encryptStreamBuf.cxx +++ b/dtool/src/prc/encryptStreamBuf.cxx @@ -73,8 +73,8 @@ EncryptStreamBuf() { _key_length = encryption_key_length; _iteration_count = encryption_iteration_count; - _read_valid = false; - _write_valid = false; + _read_ctx = NULL; + _write_ctx = NULL; _read_overflow_buffer = NULL; _in_read_overflow_buffer = 0; @@ -110,7 +110,6 @@ open_read(istream *source, bool owns_source, const string &password) { _source = source; _owns_source = owns_source; - _read_valid = false; // Now read the header information. StreamReader sr(_source, false); @@ -123,6 +122,11 @@ open_read(istream *source, bool owns_source, const string &password) { if (cipher == NULL) { prc_cat.error() << "Unknown encryption algorithm in stream.\n"; + + if (_read_ctx != NULL) { + EVP_CIPHER_CTX_free(_read_ctx); + _read_ctx = NULL; + } return; } @@ -143,17 +147,25 @@ open_read(istream *source, bool owns_source, const string &password) { string iv = sr.extract_bytes(iv_length); + if (_read_ctx != NULL) { + EVP_CIPHER_CTX_reset(_read_ctx); + } else { + _read_ctx = EVP_CIPHER_CTX_new(); + } + nassertv(_read_ctx != NULL); + // Initialize the context int result; - result = EVP_DecryptInit(&_read_ctx, cipher, NULL, (unsigned char *)iv.data()); + result = EVP_DecryptInit(_read_ctx, cipher, NULL, (unsigned char *)iv.data()); nassertv(result > 0); - result = EVP_CIPHER_CTX_set_key_length(&_read_ctx, key_length); + result = EVP_CIPHER_CTX_set_key_length(_read_ctx, key_length); if (result <= 0) { prc_cat.error() << "Invalid key length " << key_length * 8 << " bits for algorithm " << OBJ_nid2sn(nid) << "\n"; - EVP_CIPHER_CTX_cleanup(&_read_ctx); + EVP_CIPHER_CTX_free(_read_ctx); + _read_ctx = NULL; return; } @@ -167,11 +179,9 @@ open_read(istream *source, bool owns_source, const string &password) { nassertv(result > 0); // Store the key within the context. - result = EVP_DecryptInit(&_read_ctx, NULL, key, NULL); + result = EVP_DecryptInit(_read_ctx, NULL, key, NULL); nassertv(result > 0); - _read_valid = true; - _read_overflow_buffer = new unsigned char[_read_block_size]; _in_read_overflow_buffer = 0; thread_consider_yield(); @@ -182,9 +192,9 @@ open_read(istream *source, bool owns_source, const string &password) { */ void EncryptStreamBuf:: close_read() { - if (_read_valid) { - EVP_CIPHER_CTX_cleanup(&_read_ctx); - _read_valid = false; + if (_read_ctx != NULL) { + EVP_CIPHER_CTX_free(_read_ctx); + _read_ctx = NULL; } if (_read_overflow_buffer != (unsigned char *)NULL) { @@ -211,7 +221,6 @@ open_write(ostream *dest, bool owns_dest, const string &password) { close_write(); _dest = dest; _owns_dest = owns_dest; - _write_valid = false; const EVP_CIPHER *cipher = EVP_get_cipherbyname(_algorithm.c_str()); @@ -219,22 +228,33 @@ open_write(ostream *dest, bool owns_dest, const string &password) { if (cipher == NULL) { prc_cat.error() << "Unknown encryption algorithm: " << _algorithm << "\n"; + + if (_write_ctx != NULL) { + EVP_CIPHER_CTX_free(_write_ctx); + _write_ctx = NULL; + } return; - }; + } int nid = EVP_CIPHER_nid(cipher); int iv_length = EVP_CIPHER_iv_length(cipher); _write_block_size = EVP_CIPHER_block_size(cipher); - unsigned char *iv = (unsigned char *)alloca(iv_length); - // Generate a random IV. It doesn't need to be cryptographically secure, // just unique. + unsigned char *iv = (unsigned char *)alloca(iv_length); RAND_pseudo_bytes(iv, iv_length); + if (_read_ctx != NULL) { + EVP_CIPHER_CTX_reset(_write_ctx); + } else { + _write_ctx = EVP_CIPHER_CTX_new(); + } + nassertv(_write_ctx != NULL); + int result; - result = EVP_EncryptInit(&_write_ctx, cipher, NULL, iv); + result = EVP_EncryptInit(_write_ctx, cipher, NULL, iv); nassertv(result > 0); // Store the appropriate key length in the context. @@ -242,12 +262,13 @@ open_write(ostream *dest, bool owns_dest, const string &password) { if (key_length == 0) { key_length = EVP_CIPHER_key_length(cipher); } - result = EVP_CIPHER_CTX_set_key_length(&_write_ctx, key_length); + result = EVP_CIPHER_CTX_set_key_length(_write_ctx, key_length); if (result <= 0) { prc_cat.error() << "Invalid key length " << key_length * 8 << " bits for algorithm " << OBJ_nid2sn(nid) << "\n"; - EVP_CIPHER_CTX_cleanup(&_write_ctx); + EVP_CIPHER_CTX_free(_write_ctx); + _write_ctx = NULL; return; } @@ -271,7 +292,7 @@ open_write(ostream *dest, bool owns_dest, const string &password) { nassertv(result > 0); // Store the key in the context. - result = EVP_EncryptInit(&_write_ctx, NULL, key, NULL); + result = EVP_EncryptInit(_write_ctx, NULL, key, NULL); nassertv(result > 0); // Now write the header information to the stream. @@ -284,7 +305,6 @@ open_write(ostream *dest, bool owns_dest, const string &password) { sw.add_uint16((uint16_t)count); sw.append_data(iv, iv_length); - _write_valid = true; thread_consider_yield(); } @@ -298,15 +318,16 @@ close_write() { write_chars(pbase(), n); pbump(-(int)n); - if (_write_valid) { + if (_write_ctx != NULL) { unsigned char *write_buffer = (unsigned char *)alloca(_write_block_size); int bytes_written = 0; - EVP_EncryptFinal(&_write_ctx, write_buffer, &bytes_written); + EVP_EncryptFinal(_write_ctx, write_buffer, &bytes_written); thread_consider_yield(); _dest->write((const char *)write_buffer, bytes_written); - _write_valid = false; + EVP_CIPHER_CTX_free(_write_ctx); + _write_ctx = NULL; } if (_owns_dest) { @@ -418,7 +439,7 @@ read_chars(char *start, size_t length) { do { // Get more bytes from the stream. - if (!_read_valid) { + if (_read_ctx == NULL) { return 0; } @@ -429,20 +450,21 @@ read_chars(char *start, size_t length) { int result; if (source_length != 0) { result = - EVP_DecryptUpdate(&_read_ctx, read_buffer, &bytes_read, + EVP_DecryptUpdate(_read_ctx, read_buffer, &bytes_read, source_buffer, source_length); } else { result = - EVP_DecryptFinal(&_read_ctx, read_buffer, &bytes_read); - _read_valid = false; + EVP_DecryptFinal(_read_ctx, read_buffer, &bytes_read); + EVP_CIPHER_CTX_free(_read_ctx); + _read_ctx = NULL; } if (result <= 0) { prc_cat.error() << "Error decrypting stream.\n"; - if (_read_valid) { - EVP_CIPHER_CTX_cleanup(&_read_ctx); - _read_valid = false; + if (_read_ctx != NULL) { + EVP_CIPHER_CTX_free(_read_ctx); + _read_ctx = NULL; } } thread_consider_yield(); @@ -472,13 +494,13 @@ read_chars(char *start, size_t length) { */ void EncryptStreamBuf:: write_chars(const char *start, size_t length) { - if (_write_valid && length != 0) { + if (_write_ctx != NULL && length != 0) { size_t max_write_buffer = length + _write_block_size; unsigned char *write_buffer = (unsigned char *)alloca(max_write_buffer); int bytes_written = 0; int result = - EVP_EncryptUpdate(&_write_ctx, write_buffer, &bytes_written, + EVP_EncryptUpdate(_write_ctx, write_buffer, &bytes_written, (unsigned char *)start, length); if (result <= 0) { prc_cat.error() diff --git a/dtool/src/prc/encryptStreamBuf.h b/dtool/src/prc/encryptStreamBuf.h index 0542457267..4861a89240 100644 --- a/dtool/src/prc/encryptStreamBuf.h +++ b/dtool/src/prc/encryptStreamBuf.h @@ -64,14 +64,12 @@ private: int _key_length; int _iteration_count; - bool _read_valid; - EVP_CIPHER_CTX _read_ctx; + EVP_CIPHER_CTX *_read_ctx; size_t _read_block_size; unsigned char *_read_overflow_buffer; size_t _in_read_overflow_buffer; - bool _write_valid; - EVP_CIPHER_CTX _write_ctx; + EVP_CIPHER_CTX *_write_ctx; size_t _write_block_size; }; diff --git a/panda/src/downloader/httpClient.cxx b/panda/src/downloader/httpClient.cxx index 26baaff0c1..f1ae5d7e7c 100644 --- a/panda/src/downloader/httpClient.cxx +++ b/panda/src/downloader/httpClient.cxx @@ -231,11 +231,7 @@ operator = (const HTTPClient ©) { */ HTTPClient:: ~HTTPClient() { - // Before we can free the context, we must remove the X509_STORE pointer - // from it, so it won't be destroyed along with it (this object is shared - // among all contexts). if (_ssl_ctx != (SSL_CTX *)NULL) { - _ssl_ctx->cert_store = NULL; SSL_CTX_free(_ssl_ctx); } @@ -1122,7 +1118,11 @@ get_ssl_ctx() { OpenSSLWrapper *sslw = OpenSSLWrapper::get_global_ptr(); sslw->notify_ssl_errors(); - SSL_CTX_set_cert_store(_ssl_ctx, sslw->get_x509_store()); + X509_STORE *store = sslw->get_x509_store(); + if (store != NULL) { + X509_STORE_up_ref(store); + } + SSL_CTX_set_cert_store(_ssl_ctx, store); return _ssl_ctx; } @@ -1511,15 +1511,17 @@ x509_name_subset(X509_NAME *name_a, X509_NAME *name_b) { for (int ai = 0; ai < count_a; ai++) { X509_NAME_ENTRY *na = X509_NAME_get_entry(name_a, ai); - int bi = X509_NAME_get_index_by_OBJ(name_b, na->object, -1); + int bi = X509_NAME_get_index_by_OBJ(name_b, X509_NAME_ENTRY_get_object(na), -1); if (bi < 0) { // This entry in name_a is not defined in name_b. return false; } X509_NAME_ENTRY *nb = X509_NAME_get_entry(name_b, bi); - if (na->value->length != nb->value->length || - memcmp(na->value->data, nb->value->data, na->value->length) != 0) { + ASN1_STRING *na_value = X509_NAME_ENTRY_get_data(na); + ASN1_STRING *nb_value = X509_NAME_ENTRY_get_data(nb); + if (na_value->length != nb_value->length || + memcmp(na_value->data, nb_value->data, na_value->length) != 0) { // This entry in name_a doesn't match that of name_b. return false; }