control: tag -1 help control: tag -1 moreinfo Hi Kurt,
I have prepared a patch that allows most of bro to build with OpenSSL 1.1. There are still some issues that I haven't been able to figure out with looking at the OpenSSL source. Please have a look at the attached patch. The remaining issues (all in bro-2.4.0+dfsg/src/file_analysis/analyzer/x509/functions.bif) are about what seems to be missing OCSP getter functions: - For OCSP_RECPID *rid: - rid->type - rid->value.byKey->length - rid->value.byKey->data - For OCSP_BASICRESP *basic: - basic->certs - basic->tbsResponseData->responderId (For my rebuild, I simply commented out those parts.) Even after we get this sorted out, I would be really uncomfortable with carrying these patches if upstream decides that supporting OpenSSL 1.1 can wait for another year or so. Cheers, -Hilko
>From 95f998455d6b052d032251ed88914a2487390c31 Mon Sep 17 00:00:00 2001 From: Hilko Bengen <ben...@debian.org> Date: Sat, 2 Jul 2016 12:39:31 +0200 Subject: [PATCH] OpenSSL 1.1 --- src/File.cc | 4 +-- src/file_analysis/analyzer/x509/X509.cc | 49 ++++++++++++++++----------- src/file_analysis/analyzer/x509/functions.bif | 46 +++++++++++++------------ 3 files changed, 57 insertions(+), 42 deletions(-) diff --git a/src/File.cc b/src/File.cc index e62ca73..74efaa4 100644 --- a/src/File.cc +++ b/src/File.cc @@ -688,7 +688,7 @@ void BroFile::InitEncrypt(const char* keyfile) // Depending on the OpenSSL version, EVP_*_cbc() // returns a const or a non-const. EVP_CIPHER* cipher_type = (EVP_CIPHER*) EVP_bf_cbc(); - cipher_ctx = new EVP_CIPHER_CTX; + cipher_ctx = EVP_CIPHER_CTX_new(); unsigned char secret[EVP_PKEY_size(pub_key)]; unsigned char* psecret = secret; @@ -743,7 +743,7 @@ void BroFile::FinishEncrypt() return; } - delete cipher_ctx; + EVP_CIPHER_CTX_free(cipher_ctx); cipher_ctx = 0; } } diff --git a/src/file_analysis/analyzer/x509/X509.cc b/src/file_analysis/analyzer/x509/X509.cc index d960474..f9ebeb0 100644 --- a/src/file_analysis/analyzer/x509/X509.cc +++ b/src/file_analysis/analyzer/x509/X509.cc @@ -138,7 +138,9 @@ RecordVal* file_analysis::X509::ParseCertificate(X509Val* cert_val, const char* // we only read 255 bytes because byte 256 is always 0. // if the string is longer than 255, that will be our null-termination, // otherwhise i2t does null-terminate. - if ( ! i2t_ASN1_OBJECT(buf, 255, ssl_cert->cert_info->key->algor->algorithm) ) + ASN1_OBJECT *algorithm; + X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(ssl_cert)); + if ( ! i2t_ASN1_OBJECT(buf, 255, algorithm) ) buf[0] = 0; pX509Cert->Assign(7, new StringVal(buf)); @@ -149,14 +151,17 @@ RecordVal* file_analysis::X509::ParseCertificate(X509Val* cert_val, const char* // actually should be (namely - rsaEncryption), so that OpenSSL will parse out the // key later. Otherwise it will just fail to parse the certificate key. - ASN1_OBJECT* old_algorithm = 0; - if ( OBJ_obj2nid(ssl_cert->cert_info->key->algor->algorithm) == NID_md5WithRSAEncryption ) + if ( X509_get_signature_nid(ssl_cert) == NID_md5WithRSAEncryption ) { - old_algorithm = ssl_cert->cert_info->key->algor->algorithm; - ssl_cert->cert_info->key->algor->algorithm = OBJ_nid2obj(NID_rsaEncryption); + X509_PUBKEY_set0_param(X509_get_X509_PUBKEY(ssl_cert), OBJ_nid2obj(NID_rsaEncryption), 0, NULL, NULL, 0); + } + else + { + ASN1_OBJECT_free(algorithm); + algorithm = 0; } - if ( ! i2t_ASN1_OBJECT(buf, 255, ssl_cert->sig_alg->algorithm) ) + if ( ! i2t_ASN1_OBJECT(buf, 255, OBJ_nid2obj(X509_get_signature_nid(ssl_cert))) ) buf[0] = 0; pX509Cert->Assign(8, new StringVal(buf)); @@ -165,14 +170,16 @@ RecordVal* file_analysis::X509::ParseCertificate(X509Val* cert_val, const char* EVP_PKEY *pkey = X509_extract_key(ssl_cert); if ( pkey != NULL ) { - if ( pkey->type == EVP_PKEY_DSA ) + if ( DSA *dsa = EVP_PKEY_get0_DSA(pkey) ) pX509Cert->Assign(9, new StringVal("dsa")); - else if ( pkey->type == EVP_PKEY_RSA ) + else if ( RSA *rsa = EVP_PKEY_get0_RSA(pkey) ) { pX509Cert->Assign(9, new StringVal("rsa")); - char *exponent = BN_bn2dec(pkey->pkey.rsa->e); + const BIGNUM *e; + RSA_get0_key(EVP_PKEY_get0_RSA(pkey), NULL, &e, NULL); + char *exponent = BN_bn2dec(e); if ( exponent != NULL ) { pX509Cert->Assign(11, new StringVal(exponent)); @@ -181,7 +188,7 @@ RecordVal* file_analysis::X509::ParseCertificate(X509Val* cert_val, const char* } } #ifndef OPENSSL_NO_EC - else if ( pkey->type == EVP_PKEY_EC ) + else if ( EC_KEY *ec = EVP_PKEY_get0_EC_KEY(pkey) ) { pX509Cert->Assign(9, new StringVal("ecdsa")); pX509Cert->Assign(12, KeyCurve(pkey)); @@ -190,8 +197,8 @@ RecordVal* file_analysis::X509::ParseCertificate(X509Val* cert_val, const char* // set key algorithm back. We do not have to free the value that we created because (I think) it // comes out of a static array from OpenSSL memory. - if ( old_algorithm ) - ssl_cert->cert_info->key->algor->algorithm = old_algorithm; + if ( algorithm ) + X509_PUBKEY_set0_param(X509_get_X509_PUBKEY(ssl_cert), algorithm, 0, NULL, NULL, 0); unsigned int length = KeyLength(pkey); if ( length > 0 ) @@ -262,7 +269,7 @@ void file_analysis::X509::ParseExtension(X509_EXTENSION* ex) BIO *bio = BIO_new(BIO_s_mem()); if( ! X509V3_EXT_print(bio, ex, 0, 0)) - M_ASN1_OCTET_STRING_print(bio,ex->value); + ASN1_STRING_print(bio,(ASN1_STRING *)X509_EXTENSION_get_data(ex)); StringVal* ext_val = GetExtensionFromBIO(bio); @@ -444,7 +451,7 @@ StringVal* file_analysis::X509::KeyCurve(EVP_PKEY *key) // well, we do not have EC-Support... return NULL; #else - if ( key->type != EVP_PKEY_EC ) + if ( EVP_PKEY_base_id(key) != EVP_PKEY_EC ) { // no EC-key - no curve name return NULL; @@ -452,7 +459,7 @@ StringVal* file_analysis::X509::KeyCurve(EVP_PKEY *key) const EC_GROUP *group; int nid; - if ( (group = EC_KEY_get0_group(key->pkey.ec)) == NULL) + if ( (group = EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(key))) == NULL) // I guess we could not parse this return NULL; @@ -473,12 +480,16 @@ unsigned int file_analysis::X509::KeyLength(EVP_PKEY *key) { assert(key != NULL); - switch(key->type) { + switch(EVP_PKEY_base_id(key)) { case EVP_PKEY_RSA: - return BN_num_bits(key->pkey.rsa->n); + const BIGNUM *n; + RSA_get0_key(EVP_PKEY_get0_RSA(key), &n, NULL, NULL); + return BN_num_bits(n); case EVP_PKEY_DSA: - return BN_num_bits(key->pkey.dsa->p); + const BIGNUM *p; + DSA_get0_pqg(EVP_PKEY_get0_DSA(key), &p, NULL, NULL); + return BN_num_bits(p); #ifndef OPENSSL_NO_EC case EVP_PKEY_EC: @@ -488,7 +499,7 @@ unsigned int file_analysis::X509::KeyLength(EVP_PKEY *key) // could not malloc bignum? return 0; - const EC_GROUP *group = EC_KEY_get0_group(key->pkey.ec); + const EC_GROUP *group = EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(key)); if ( ! group ) { diff --git a/src/file_analysis/analyzer/x509/functions.bif b/src/file_analysis/analyzer/x509/functions.bif index 216f4c6..9524f0a 100644 --- a/src/file_analysis/analyzer/x509/functions.bif +++ b/src/file_analysis/analyzer/x509/functions.bif @@ -331,8 +331,8 @@ function x509_ocsp_verify%(certs: x509_opaque_vector, ocsp_reply: string, root_c result = X509_verify_cert(csc); if ( result != 1 ) { - const char *reason = X509_verify_cert_error_string((*csc).error); - rval = x509_result_record(result, X509_verify_cert_error_string((*csc).error)); + const char *reason = X509_verify_cert_error_string(X509_STORE_CTX_get_error(csc)); + rval = x509_result_record(result, X509_verify_cert_error_string(X509_STORE_CTX_get_error(csc))); goto x509_ocsp_cleanup; } @@ -357,15 +357,15 @@ function x509_ocsp_verify%(certs: x509_opaque_vector, ocsp_reply: string, root_c else { // issuer not in list sent by server, check store - X509_OBJECT obj; - int lookup = X509_STORE_get_by_subject(csc, X509_LU_X509, X509_get_subject_name(cert), &obj); + X509_OBJECT *obj = X509_OBJECT_new(); + int lookup = X509_STORE_get_by_subject(csc, X509_LU_X509, X509_get_subject_name(cert), obj); if ( lookup <= 0) { rval = x509_result_record(lookup, "Could not find issuer of host certificate"); goto x509_ocsp_cleanup; } - certid = OCSP_cert_to_id(NULL, cert, obj.data.x509); + certid = OCSP_cert_to_id(NULL, cert,X509_OBJECT_get0_X509( obj)); } @@ -376,18 +376,22 @@ function x509_ocsp_verify%(certs: x509_opaque_vector, ocsp_reply: string, root_c } // for now, assume we have one reply... - single = sk_OCSP_SINGLERESP_value(basic->tbsResponseData->responses, 0); + single = OCSP_resp_get0(basic, 0); if ( ! single ) { rval = x509_result_record(-1, "Could not lookup OCSP response information"); goto x509_ocsp_cleanup; } - if ( OCSP_id_cmp(certid, single->certId) != 0 ) + if ( OCSP_id_cmp(certid, OCSP_SINGLERESP_get0_id(single)) != 0 ) return x509_result_record(-1, "OCSP reply is not for host certificate"); // next - check freshness of proof... - if ( ! ASN1_GENERALIZEDTIME_check(single->thisUpdate) || ! ASN1_GENERALIZEDTIME_check(single->nextUpdate) ) + ASN1_GENERALIZEDTIME *thisUpdate; + ASN1_GENERALIZEDTIME *nextUpdate; + int type; + type = OCSP_single_get0_status(single, NULL, NULL, &thisUpdate, &nextUpdate); + if ( ! ASN1_GENERALIZEDTIME_check(thisUpdate) || ! ASN1_GENERALIZEDTIME_check(nextUpdate) ) { rval = x509_result_record(-1, "OCSP reply contains invalid dates"); goto x509_ocsp_cleanup; @@ -400,16 +404,16 @@ function x509_ocsp_verify%(certs: x509_opaque_vector, ocsp_reply: string, root_c // Well, we will do it manually. - if ( X509_cmp_time(single->thisUpdate, &vtime) > 0 ) + if ( X509_cmp_time(thisUpdate, &vtime) > 0 ) rval = x509_result_record(-1, "OCSP reply specifies time in future"); - else if ( X509_cmp_time(single->nextUpdate, &vtime) < 0 ) + else if ( X509_cmp_time(nextUpdate, &vtime) < 0 ) rval = x509_result_record(-1, "OCSP reply expired"); - else if ( single->certStatus->type != V_OCSP_CERTSTATUS_GOOD ) - rval = x509_result_record(-1, OCSP_cert_status_str(single->certStatus->type)); + else if ( type != V_OCSP_CERTSTATUS_GOOD ) + rval = x509_result_record(-1, OCSP_cert_status_str(type)); // if we have no error so far, we are done. if ( !rval ) - rval = x509_result_record(1, OCSP_cert_status_str(single->certStatus->type)); + rval = x509_result_record(1, OCSP_cert_status_str(type)); x509_ocsp_cleanup: @@ -486,18 +490,18 @@ function x509_verify%(certs: x509_opaque_vector, root_certs: table_string_of_str if ( ! untrusted_certs ) return x509_result_record(-1, "Problem initializing list of untrusted certificates"); - X509_STORE_CTX csc; - X509_STORE_CTX_init(&csc, ctx, cert, untrusted_certs); - X509_STORE_CTX_set_time(&csc, 0, (time_t) verify_time); - X509_STORE_CTX_set_flags(&csc, X509_V_FLAG_USE_CHECK_TIME); + X509_STORE_CTX *csc = X509_STORE_CTX_new(); + X509_STORE_CTX_init(csc, ctx, cert, untrusted_certs); + X509_STORE_CTX_set_time(csc, 0, (time_t) verify_time); + X509_STORE_CTX_set_flags(csc, X509_V_FLAG_USE_CHECK_TIME); - int result = X509_verify_cert(&csc); + int result = X509_verify_cert(csc); VectorVal* chainVector = 0; if ( result == 1 ) // we have a valid chain. try to get it... { - STACK_OF(X509)* chain = X509_STORE_CTX_get1_chain(&csc); // get1 = deep copy + STACK_OF(X509)* chain = X509_STORE_CTX_get1_chain(csc); // get1 = deep copy if ( ! chain ) { @@ -529,11 +533,11 @@ function x509_verify%(certs: x509_opaque_vector, root_certs: table_string_of_str x509_verify_chainerror: - X509_STORE_CTX_cleanup(&csc); + X509_STORE_CTX_cleanup(csc); sk_X509_free(untrusted_certs); - RecordVal* rrecord = x509_result_record(csc.error, X509_verify_cert_error_string(csc.error), chainVector); + RecordVal* rrecord = x509_result_record(X509_STORE_CTX_get_error(csc), X509_verify_cert_error_string(X509_STORE_CTX_get_error(csc)), chainVector); return rrecord; %} -- 2.8.1