summaryrefslogtreecommitdiff
path: root/print-esp.c
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2017-09-01 04:00:38 -0700
committerGuy Harris <guy@alum.mit.edu>2017-09-01 04:00:38 -0700
commit6f0750ee0c5e19c6c2586d4d3ffa897853b8341b (patch)
tree4b3b582b96473ff8b49a0787ecb5a7c236330bdf /print-esp.c
parent0d2cdb5dad1a983d0e1884497e439efb39c9609d (diff)
downloadtcpdump-6f0750ee0c5e19c6c2586d4d3ffa897853b8341b.tar.gz
Make the ESP decryption not crash with OpenSSL 1.1.
While we're at it, free the cipher context if we fail to allocate the output buffer for decryption.
Diffstat (limited to 'print-esp.c')
-rw-r--r--print-esp.c43
1 files changed, 39 insertions, 4 deletions
diff --git a/print-esp.c b/print-esp.c
index f2b4ab3c..d12b97da 100644
--- a/print-esp.c
+++ b/print-esp.c
@@ -145,6 +145,39 @@ EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx)
}
#endif
+#ifdef HAVE_EVP_CIPHERINIT_EX
+/*
+ * Initialize the cipher by calling EVP_CipherInit_ex(), because
+ * calling EVP_CipherInit() will reset the cipher context, clearing
+ * the cipher, so calling it twice, with the second call having a
+ * null cipher, will clear the already-set cipher. EVP_CipherInit_ex(),
+ * however, won't reset the cipher context, so you can use it to specify
+ * the IV oin a second call after a first call to EVP_CipherInit_ex()
+ * to set the cipher and the key.
+ *
+ * XXX - is there some reason why we need to make two calls?
+ */
+static int
+set_cipher_parameters(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
+ const unsigned char *key,
+ const unsigned char *iv, int enc)
+{
+ return EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, enc);
+}
+#else
+/*
+ * Initialize the cipher by calling EVP_CipherInit(), because we don't
+ * have EVP_CipherInit_ex(); we rely on it not trashing the context.
+ */
+static int
+set_cipher_parameters(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
+ const unsigned char *key,
+ const unsigned char *iv, int enc)
+{
+ return EVP_CipherInit(ctx, cipher, key, iv, enc);
+}
+#endif
+
/*
* this will adjust ndo_packetp and ndo_snapend to new buffer!
*/
@@ -190,9 +223,9 @@ int esp_print_decrypt_buffer_by_ikev2(netdissect_options *ndo,
ctx = EVP_CIPHER_CTX_new();
if (ctx == NULL)
return 0;
- if (EVP_CipherInit(ctx, sa->evp, sa->secret, NULL, 0) < 0)
+ if (set_cipher_parameters(ctx, sa->evp, sa->secret, NULL, 0) < 0)
(*ndo->ndo_warning)(ndo, "espkey init failed");
- EVP_CipherInit(ctx, NULL, NULL, iv, 0);
+ set_cipher_parameters(ctx, NULL, NULL, iv, 0);
/*
* Allocate a buffer for the decrypted data.
* The output buffer must be separate from the input buffer, and
@@ -203,6 +236,7 @@ int esp_print_decrypt_buffer_by_ikev2(netdissect_options *ndo,
output_buffer = (u_char *)malloc(output_buffer_size);
if (output_buffer == NULL) {
(*ndo->ndo_warning)(ndo, "can't allocate memory for decryption buffer");
+ EVP_CIPHER_CTX_free(ctx);
return 0;
}
EVP_Cipher(ctx, output_buffer, buf, len);
@@ -735,11 +769,11 @@ esp_print(netdissect_options *ndo,
if (sa->evp) {
ctx = EVP_CIPHER_CTX_new();
if (ctx != NULL) {
- if (EVP_CipherInit(ctx, sa->evp, secret, NULL, 0) < 0)
+ if (set_cipher_parameters(ctx, sa->evp, secret, NULL, 0) < 0)
(*ndo->ndo_warning)(ndo, "espkey init failed");
p = ivoff;
- EVP_CipherInit(ctx, NULL, NULL, p, 0);
+ set_cipher_parameters(ctx, NULL, NULL, p, 0);
len = ep - (p + ivlen);
/*
@@ -753,6 +787,7 @@ esp_print(netdissect_options *ndo,
output_buffer = (u_char *)malloc(output_buffer_size);
if (output_buffer == NULL) {
(*ndo->ndo_warning)(ndo, "can't allocate memory for decryption buffer");
+ EVP_CIPHER_CTX_free(ctx);
return -1;
}