Support building with OpenSSL 1.1.0

This commit is contained in:
rdb 2016-12-24 22:19:51 +01:00
parent 7d414500c6
commit 122d9dd3ff
3 changed files with 67 additions and 45 deletions

View File

@ -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()

View File

@ -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;
};

View File

@ -231,11 +231,7 @@ operator = (const HTTPClient &copy) {
*/
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;
}