From aedd25c3a2b06d91bac874a1cd89941e7da740c4 Mon Sep 17 00:00:00 2001 From: vincent Date: Mon, 1 Aug 2016 09:34:56 +0000 Subject: [PATCH] Add compatibility with OpenSSL 1.1.0 pre5 and previous versions Add some checks to know which OpenSSL version is used, to be sure the code follows the syntax of the version used (including 1.1.0). --- ncat/ncat_ssl.c | 19 ++++++ ncat/test/test-wildcard.c | 4 ++ nping/Crypto.cc | 123 +++++++++++++++++++++++++++++--------- nse_openssl.cc | 116 +++++++++++++++++++++++++++++++++++ nse_ssl_cert.cc | 17 +++++- 5 files changed, 249 insertions(+), 30 deletions(-) diff --git a/ncat/ncat_ssl.c b/ncat/ncat_ssl.c index 3db40d480..700896ab7 100644 --- a/ncat/ncat_ssl.c +++ b/ncat/ncat_ssl.c @@ -315,7 +315,12 @@ static int cert_match_dnsname(X509 *cert, const char *hostname, /* We must copy this address into a temporary variable because ASN1_item_d2i increments it. We don't want it to corrupt ext->value->data. */ +#if OPENSSL_VERSION_NUMBER < 0x10100000L data = ext->value->data; +#else + ASN1_OCTET_STRING* asn1_str = X509_EXTENSION_get_data(ext); + data = asn1_str->data; +#endif /* Here we rely on the fact that the internal representation (the "i" in "i2d") for NID_subject_alt_name is STACK_OF(GENERAL_NAME). Converting it to a stack of CONF_VALUE with a i2v method is not satisfactory, because a @@ -323,13 +328,27 @@ static int cert_match_dnsname(X509 *cert, const char *hostname, presence of null bytes. */ #if (OPENSSL_VERSION_NUMBER > 0x00907000L) if (method->it != NULL) { + #if OPENSSL_VERSION_NUMBER < 0x10100000L gen_names = (STACK_OF(GENERAL_NAME) *) ASN1_item_d2i(NULL, (const unsigned char **) &data, ext->value->length, ASN1_ITEM_ptr(method->it)); + #else + ASN1_OCTET_STRING* asn1_str_a = X509_EXTENSION_get_data(ext); + gen_names = (STACK_OF(GENERAL_NAME) *) ASN1_item_d2i(NULL, + (const unsigned char **) &data, + asn1_str_a->length, ASN1_ITEM_ptr(method->it)); + #endif } else { + #if OPENSSL_VERSION_NUMBER < 0x10100000L gen_names = (STACK_OF(GENERAL_NAME) *) method->d2i(NULL, (const unsigned char **) &data, ext->value->length); + #else + ASN1_OCTET_STRING* asn1_str_b = X509_EXTENSION_get_data(ext); + gen_names = (STACK_OF(GENERAL_NAME) *) method->d2i(NULL, + (const unsigned char **) &data, + asn1_str_b->length); + #endif } #else gen_names = (STACK_OF(GENERAL_NAME) *) method->d2i(NULL, diff --git a/ncat/test/test-wildcard.c b/ncat/test/test-wildcard.c index 6865b8827..25157ec2b 100644 --- a/ncat/test/test-wildcard.c +++ b/ncat/test/test-wildcard.c @@ -253,7 +253,11 @@ static int set_dNSNames(X509 *cert, const struct lstr dNSNames[]) if (gen_name == NULL) goto stack_err; gen_name->type = GEN_DNS; + #if OPENSSL_VERSION_NUMBER < 0x10100000L gen_name->d.dNSName = M_ASN1_IA5STRING_new(); + #else + gen_name->d.dNSName = ASN1_IA5STRING_new(); + #endif if (gen_name->d.dNSName == NULL) goto name_err; if (ASN1_STRING_set(gen_name->d.dNSName, name->s, name->len) == 0) diff --git a/nping/Crypto.cc b/nping/Crypto.cc index 0524652f6..e747d40b3 100644 --- a/nping/Crypto.cc +++ b/nping/Crypto.cc @@ -178,21 +178,39 @@ int Crypto::aes128_cbc_encrypt(u8 *inbuff, size_t inlen, u8 *dst_buff, u8 *key, #ifdef HAVE_OPENSSL if( o.doCrypto() ){ int flen=0, flen2=0; - EVP_CIPHER_CTX ctx; - EVP_CIPHER_CTX_init(&ctx); - EVP_CIPHER_CTX_set_padding(&ctx, 0); - int result=OP_SUCCESS; - if( EVP_EncryptInit(&ctx, EVP_aes_128_cbc(), key, iv)==0 ){ - nping_print(DBG_4, "EVP_EncryptInit() failed"); - result=OP_FAILURE; - }else if( EVP_EncryptUpdate(&ctx, dst_buff, &flen, inbuff, (int)inlen)==0 ){ - nping_print(DBG_4, "EVP_EncryptUpdate() failed"); - result=OP_FAILURE; - }else if( EVP_EncryptFinal(&ctx, dst_buff+flen, &flen2)==0 ){ - nping_print(DBG_4, "EVP_EncryptFinal() failed"); - result=OP_FAILURE; - } - EVP_CIPHER_CTX_cleanup(&ctx); + #if OPENSSL_VERSION_NUMBER < 0x10100000L + EVP_CIPHER_CTX ctx; + EVP_CIPHER_CTX_init(&ctx); + EVP_CIPHER_CTX_set_padding(&ctx, 0); + int result=OP_SUCCESS; + if( EVP_EncryptInit(&ctx, EVP_aes_128_cbc(), key, iv)==0 ){ + nping_print(DBG_4, "EVP_EncryptInit() failed"); + result=OP_FAILURE; + }else if( EVP_EncryptUpdate(&ctx, dst_buff, &flen, inbuff, (int)inlen)==0 ){ + nping_print(DBG_4, "EVP_EncryptUpdate() failed"); + result=OP_FAILURE; + }else if( EVP_EncryptFinal(&ctx, dst_buff+flen, &flen2)==0 ){ + nping_print(DBG_4, "EVP_EncryptFinal() failed"); + result=OP_FAILURE; + } + EVP_CIPHER_CTX_cleanup(&ctx); + #else + EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); + EVP_CIPHER_CTX_reset(ctx); + EVP_CIPHER_CTX_set_padding(ctx, 0); + int result=OP_SUCCESS; + if( EVP_EncryptInit(ctx, EVP_aes_128_cbc(), key, iv)==0 ){ + nping_print(DBG_4, "EVP_EncryptInit() failed"); + result=OP_FAILURE; + }else if( EVP_EncryptUpdate(ctx, dst_buff, &flen, inbuff, (int)inlen)==0 ){ + nping_print(DBG_4, "EVP_EncryptUpdate() failed"); + result=OP_FAILURE; + }else if( EVP_EncryptFinal(ctx, dst_buff+flen, &flen2)==0 ){ + nping_print(DBG_4, "EVP_EncryptFinal() failed"); + result=OP_FAILURE; + } + EVP_CIPHER_CTX_cleanup(ctx); + #endif return result; } #endif @@ -213,19 +231,35 @@ int Crypto::aes128_cbc_decrypt(u8 *inbuff, size_t inlen, u8 *dst_buff, u8 *key, #ifdef HAVE_OPENSSL if( o.doCrypto() ){ int flen1=0, flen2=0; - EVP_CIPHER_CTX ctx; - EVP_CIPHER_CTX_init(&ctx); - EVP_CIPHER_CTX_set_padding(&ctx, 0); - int result=OP_SUCCESS; - if( EVP_DecryptInit(&ctx, EVP_aes_128_cbc(), key, iv)==0 ){ - nping_print(DBG_4, "EVP_DecryptInit() failed"); - result=OP_FAILURE; - }else if( EVP_DecryptUpdate(&ctx, dst_buff, &flen1, inbuff, (int)inlen)==0 ){ - nping_print(DBG_4, "EVP_DecryptUpdate() failed"); - result=OP_FAILURE; - }else if( EVP_DecryptFinal(&ctx, dst_buff+flen1, &flen2)==0 ){ - nping_print(DBG_4, "OpenSSL bug: it says EVP_DecryptFinal() failed when it didn't (%s).", - ERR_error_string(ERR_peek_last_error(), NULL)); + #if OPENSSL_VERSION_NUMBER < 0x10100000L + EVP_CIPHER_CTX ctx; + EVP_CIPHER_CTX_init(&ctx); + EVP_CIPHER_CTX_set_padding(&ctx, 0); + int result=OP_SUCCESS; + if( EVP_DecryptInit(&ctx, EVP_aes_128_cbc(), key, iv)==0 ){ + nping_print(DBG_4, "EVP_DecryptInit() failed"); + result=OP_FAILURE; + }else if( EVP_DecryptUpdate(&ctx, dst_buff, &flen1, inbuff, (int)inlen)==0 ){ + nping_print(DBG_4, "EVP_DecryptUpdate() failed"); + result=OP_FAILURE; + }else if( EVP_DecryptFinal(&ctx, dst_buff+flen1, &flen2)==0 ){ + nping_print(DBG_4, "OpenSSL bug: it says EVP_DecryptFinal() failed when it didn't (%s).", + ERR_error_string(ERR_peek_last_error(), NULL)); + #else + EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); + EVP_CIPHER_CTX_reset(ctx); + EVP_CIPHER_CTX_set_padding(ctx, 0); + int result=OP_SUCCESS; + if( EVP_DecryptInit(ctx, EVP_aes_128_cbc(), key, iv)==0 ){ + nping_print(DBG_4, "EVP_DecryptInit() failed"); + result=OP_FAILURE; + }else if( EVP_DecryptUpdate(ctx, dst_buff, &flen1, inbuff, (int)inlen)==0 ){ + nping_print(DBG_4, "EVP_DecryptUpdate() failed"); + result=OP_FAILURE; + }else if( EVP_DecryptFinal(ctx, dst_buff+flen1, &flen2)==0 ){ + nping_print(DBG_4, "OpenSSL bug: it says EVP_DecryptFinal() failed when it didn't (%s).", + ERR_error_string(ERR_peek_last_error(), NULL)); + #endif /* We do not return OP_FAILURE in this case because the * EVP_DecryptFinal() function seems to be buggy and fails when it shouldn't. * We are passing a buffer whose length is multiple of the AES block @@ -252,7 +286,11 @@ int Crypto::aes128_cbc_decrypt(u8 *inbuff, size_t inlen, u8 *dst_buff, u8 *key, //ERR_free_strings(); //ERR_pop_to_mark(); } - EVP_CIPHER_CTX_cleanup(&ctx); + #if OPENSSL_VERSION_NUMBER < 0x10100000L + EVP_CIPHER_CTX_cleanup(&ctx); + #else + EVP_CIPHER_CTX_reset(ctx); + #endif return result; } #endif @@ -289,6 +327,7 @@ u8 *Crypto::deriveKey(const u8 *from, size_t fromlen, size_t *final_len){ static u8 hash[MAX(SHA256_HASH_LEN, EVP_MAX_MD_SIZE)]; static u8 next[MAX(SHA256_HASH_LEN, EVP_MAX_MD_SIZE)]; unsigned int lastlen; + #if OPENSSL_VERSION_NUMBER < 0x10100000L EVP_MD_CTX ctx; EVP_MD_CTX_init(&ctx); @@ -310,7 +349,33 @@ u8 *Crypto::deriveKey(const u8 *from, size_t fromlen, size_t *final_len){ } if(final_len!=NULL) *final_len=SHA256_HASH_LEN; + EVP_MD_CTX_cleanup(&ctx); + #else + EVP_MD_CTX *ctx = EVP_MD_CTX_new(); + EVP_MD_CTX_init(ctx); + + if( EVP_MD_size(EVP_sha256()) != SHA256_HASH_LEN ) + nping_fatal(QT_2, "OpenSSL is broken. SHA256 len is %d\n", EVP_MD_size(EVP_sha256()) ); + + /* Compute the SHA256 hash of the supplied buffer */ + EVP_DigestInit(ctx, EVP_sha256()); + EVP_DigestUpdate(ctx, from, fromlen); + EVP_DigestFinal(ctx, hash, &lastlen); + + /* Now compute the 1000th hash of that hash */ + for(int i=0; i #include #include +#include extern "C" { @@ -384,7 +385,7 @@ static void asn1_time_to_obj(lua_State *L, const ASN1_TIME *s) /* This is a helper function for x509_validity_to_table. It builds a table with the two members "notBefore" and "notAfter", whose values are what is returned from asn1_time_to_obj. */ -static void x509_validity_to_table(lua_State *L, const X509 *cert) +static void x509_validity_to_table(lua_State *L, X509 *cert) { lua_newtable(L); @@ -527,7 +528,11 @@ static int parse_ssl_cert(lua_State *L, X509 *cert) lua_setfield(L, -2, "subject"); } +#if OPENSSL_VERSION_NUMBER < 0x10100000L const char *sig_algo = OBJ_nid2ln(OBJ_obj2nid(cert->sig_alg->algorithm)); +#else + const char *sig_algo = OBJ_nid2ln(X509_get_signature_nid(cert)); +#endif lua_pushstring(L, sig_algo); lua_setfield(L, -2, "sig_algorithm"); @@ -545,7 +550,11 @@ static int parse_ssl_cert(lua_State *L, X509 *cert) pubkey = X509_get_pubkey(cert); lua_newtable(L); +#if OPENSSL_VERSION_NUMBER < 0x10100000L pkey_type = EVP_PKEY_type(pubkey->type); +#else + pkey_type = EVP_PKEY_base_id(pubkey); +#endif #ifdef EVP_PKEY_EC if (pkey_type == EVP_PKEY_EC) { lua_push_ecdhparams(L, pubkey); @@ -558,7 +567,13 @@ static int parse_ssl_cert(lua_State *L, X509 *cert) bignum_data_t * data = (bignum_data_t *) lua_newuserdata( L, sizeof(bignum_data_t)); luaL_getmetatable( L, "BIGNUM" ); lua_setmetatable( L, -2 ); + #if OPENSSL_VERSION_NUMBER < 0x10100000L data->bn = rsa->e; + #else + BIGNUM *n, *e, *d; + RSA_get0_key(rsa, &n, &e, &d); + data->bn = e; + #endif lua_setfield(L, -2, "exponent"); } lua_pushstring(L, pkey_type_to_string(pkey_type));