diff options
author | Guy Harris <guy@alum.mit.edu> | 2016-06-22 21:14:40 -0700 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2016-06-22 21:14:40 -0700 |
commit | b1f305da3ddf635522bdcd6c88918beaea330968 (patch) | |
tree | 902044f80b10a4de19692039fc2aa4f7abcc1714 | |
parent | 6334c9435e782cc73406e03a4328da58630c6639 (diff) | |
download | tcpdump-b1f305da3ddf635522bdcd6c88918beaea330968.tar.gz |
Handle OpenSSL 1.1.x.
In 1.1.x, EVP_CIPHER_CTX is an opaque structure, so we can't declare it
on the stack.
Instead, if we don't have EVP_CIPHER_CTX_new() and EVP_CIPHER_CTX_free()
in libcrypto, define our own versions, with the same signatures as the
ones in OpenSSL 1.1.x's libcrypto, and have the code use
EVP_CIPHER_CTX_new() to allocate the structure and EVP_CIPHER_CTX_free()
to free it.
-rw-r--r-- | config.h.in | 3 | ||||
-rwxr-xr-x | configure | 21 | ||||
-rw-r--r-- | configure.in | 11 | ||||
-rw-r--r-- | print-esp.c | 63 |
4 files changed, 80 insertions, 18 deletions
diff --git a/config.h.in b/config.h.in index 6f6bb11a..27ba4b10 100644 --- a/config.h.in +++ b/config.h.in @@ -34,6 +34,9 @@ /* Define to 1 if you have the `ether_ntohost' function. */ #undef HAVE_ETHER_NTOHOST +/* Define to 1 if you have the `EVP_CIPHER_CTX_new' function. */ +#undef HAVE_EVP_CIPHER_CTX_NEW + /* Define to 1 if you have the <fcntl.h> header file. */ #undef HAVE_FCNTL_H @@ -8041,7 +8041,8 @@ _ACEOF fi - for ac_header in openssl/evp.h + if test "$ac_cv_lib_crypto_DES_cbc_encrypt" = "yes"; then + for ac_header in openssl/evp.h do : ac_fn_c_check_header_mongrel "$LINENO" "openssl/evp.h" "ac_cv_header_openssl_evp_h" "$ac_includes_default" if test "x$ac_cv_header_openssl_evp_h" = xyes; then : @@ -8053,6 +8054,24 @@ fi done + # + # OK, do we have EVP_CIPHER_CTX_new? + # If so, we use it to allocate an + # EVP_CIPHER_CTX, as EVP_CIPHER_CTX may be + # opaque; otherwise, we allocate it ourselves. + # + for ac_func in EVP_CIPHER_CTX_new +do : + ac_fn_c_check_func "$LINENO" "EVP_CIPHER_CTX_new" "ac_cv_func_EVP_CIPHER_CTX_new" +if test "x$ac_cv_func_EVP_CIPHER_CTX_new" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_EVP_CIPHER_CTX_NEW 1 +_ACEOF + +fi +done + + fi fi diff --git a/configure.in b/configure.in index 8ceb46bb..22ecee6f 100644 --- a/configure.in +++ b/configure.in @@ -918,7 +918,16 @@ if test "$want_libcrypto" != "no"; then AC_CHECK_HEADER(openssl/crypto.h, [ AC_CHECK_LIB(crypto, DES_cbc_encrypt) - AC_CHECK_HEADERS(openssl/evp.h) + if test "$ac_cv_lib_crypto_DES_cbc_encrypt" = "yes"; then + AC_CHECK_HEADERS(openssl/evp.h) + # + # OK, do we have EVP_CIPHER_CTX_new? + # If so, we use it to allocate an + # EVP_CIPHER_CTX, as EVP_CIPHER_CTX may be + # opaque; otherwise, we allocate it ourselves. + # + AC_CHECK_FUNCS(EVP_CIPHER_CTX_new) + fi ]) fi diff --git a/print-esp.c b/print-esp.c index 247796da..8339a567 100644 --- a/print-esp.c +++ b/print-esp.c @@ -117,6 +117,32 @@ struct sa_list { int secretlen; }; +#ifndef HAVE_EVP_CIPHER_CTX_NEW +/* + * Allocate an EVP_CIPHER_CTX. + * Used if we have an older version of OpenSSL that doesn't provide + * routines to allocate and free them. + */ +static EVP_CIPHER_CTX * +EVP_CIPHER_CTX_new(void) +{ + EVP_CIPHER_CTX *ctx; + + ctx = malloc(sizeof (EVP_CIPHER_CTX)); + if (ctx == NULL) + return (NULL); + memset(ctx, 0, sizeof(*ctx)); + return (ctx); +} + +static void +EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx) +{ + EVP_CIPHER_CTX_cleanup(ctx); + free(ctx); +} +#endif + /* * this will adjust ndo_packetp and ndo_snapend to new buffer! */ @@ -129,7 +155,7 @@ int esp_print_decrypt_buffer_by_ikev2(netdissect_options *ndo, struct sa_list *sa; const u_char *iv; int len; - EVP_CIPHER_CTX ctx; + EVP_CIPHER_CTX *ctx; /* initiator arg is any non-zero value */ if(initiator) initiator=1; @@ -157,12 +183,14 @@ int esp_print_decrypt_buffer_by_ikev2(netdissect_options *ndo, if(end <= buf) return 0; - memset(&ctx, 0, sizeof(ctx)); - if (EVP_CipherInit(&ctx, sa->evp, sa->secret, NULL, 0) < 0) + ctx = EVP_CIPHER_CTX_new(); + if (ctx == NULL) + return 0; + if (EVP_CipherInit(ctx, sa->evp, sa->secret, NULL, 0) < 0) (*ndo->ndo_warning)(ndo, "espkey init failed"); - EVP_CipherInit(&ctx, NULL, NULL, iv, 0); - EVP_Cipher(&ctx, buf, buf, len); - EVP_CIPHER_CTX_cleanup(&ctx); + EVP_CipherInit(ctx, NULL, NULL, iv, 0); + EVP_Cipher(ctx, buf, buf, len); + EVP_CIPHER_CTX_free(ctx); ndo->ndo_packetp = buf; ndo->ndo_snapend = end; @@ -568,7 +596,7 @@ esp_print(netdissect_options *ndo, int ivlen = 0; const u_char *ivoff; const u_char *p; - EVP_CIPHER_CTX ctx; + EVP_CIPHER_CTX *ctx; #endif esp = (const struct newesp *)bp; @@ -672,15 +700,18 @@ esp_print(netdissect_options *ndo, ep = ep - sa->authlen; if (sa->evp) { - memset(&ctx, 0, sizeof(ctx)); - if (EVP_CipherInit(&ctx, sa->evp, secret, NULL, 0) < 0) - (*ndo->ndo_warning)(ndo, "espkey init failed"); - - p = ivoff; - EVP_CipherInit(&ctx, NULL, NULL, p, 0); - EVP_Cipher(&ctx, p + ivlen, p + ivlen, ep - (p + ivlen)); - EVP_CIPHER_CTX_cleanup(&ctx); - advance = ivoff - (const u_char *)esp + ivlen; + ctx = EVP_CIPHER_CTX_new(); + if (ctx != NULL) { + if (EVP_CipherInit(ctx, sa->evp, secret, NULL, 0) < 0) + (*ndo->ndo_warning)(ndo, "espkey init failed"); + + p = ivoff; + EVP_CipherInit(ctx, NULL, NULL, p, 0); + EVP_Cipher(ctx, p + ivlen, p + ivlen, ep - (p + ivlen)); + EVP_CIPHER_CTX_free(ctx); + advance = ivoff - (const u_char *)esp + ivlen; + } else + advance = sizeof(struct newesp); } else advance = sizeof(struct newesp); |