summaryrefslogtreecommitdiff
path: root/print-esp.c
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2019-03-30 18:08:02 -0700
committerGuy Harris <guy@alum.mit.edu>2019-03-30 18:08:02 -0700
commitada17ed4961d6ab68525d923b4008df6ff05782a (patch)
treeb27fdd7f45116eb2b834938a5e5adc3d72070892 /print-esp.c
parentfefd7f527fc27ef466d946a42d884eef7f9fc77c (diff)
downloadtcpdump-ada17ed4961d6ab68525d923b4008df6ff05782a.tar.gz
Clean up code a bit.
"ivoff" is a pointer to the IV, not the offset of the IV; call it ivptr. Have a variable that points to the beginning of the ciphertext, and use that. Fix the check that makes sure the authentication data/integrity check value length isn't too big - it needs to make sure that it doesn't go before the beginning of the ciphertext, i.e. doesn't overlap with the IV. Don't bother with a variable pointing to the secret, just pass sa->secret. Fix the check that makes sure the padding length isn't too big - make sure it, plus 2 for the padding length and next header bytes, isn't bigger than the ciphertext length. Update a test to reflect the stricter length checks.
Diffstat (limited to 'print-esp.c')
-rw-r--r--print-esp.c89
1 files changed, 35 insertions, 54 deletions
diff --git a/print-esp.c b/print-esp.c
index ae6dc27b..1b440c08 100644
--- a/print-esp.c
+++ b/print-esp.c
@@ -688,12 +688,10 @@ esp_print(netdissect_options *ndo,
const struct ip *ip;
struct sa_list *sa = NULL;
const struct ip6_hdr *ip6 = NULL;
- int advance;
- u_int ctlen;
- u_char *secret;
+ const u_char *ivptr;
u_int ivlen;
- const u_char *ivoff;
- const u_char *p;
+ const u_char *ctptr;
+ u_int ctlen;
EVP_CIPHER_CTX *ctx;
unsigned int block_size, buffer_size;
u_char *input_buffer, *output_buffer;
@@ -704,16 +702,6 @@ esp_print(netdissect_options *ndo,
ndo->ndo_protocol = "esp";
esp = (const struct newesp *)bp;
-#ifdef HAVE_LIBCRYPTO
- secret = NULL;
- advance = 0;
-#endif
-
-#if 0
- /* keep secret out of a register */
- p = (u_char *)&secret;
-#endif
-
/* 'ep' points to the end of available data. */
ep = ndo->ndo_snapend;
@@ -787,21 +775,38 @@ esp_print(netdissect_options *ndo,
return;
/* pointer to the IV, if there is one */
- ivoff = (const u_char *)(esp + 1) + 0;
+ ivptr = (const u_char *)(esp + 1) + 0;
/* length of the IV, if there is one; 0, if there isn't */
ivlen = sa->ivlen;
- secret = sa->secret;
+
+ /*
+ * Get a pointer to the ciphertext.
+ *
+ * p points to the beginning of the payload, i.e. to the
+ * initialization vector, so if we skip past the initialization
+ * vector, it points to the beginning of the ciphertext.
+ */
+ ctptr = ivptr + ivlen;
+
/*
* Make sure the authentication data/integrity check value length
- * isn't bigger than the total amount of data available and, if
- * not, slice that off.
+ * isn't bigger than the total amount of data available after
+ * the ESP header and initialization vector is removed and,
+ * if not, slice the authentication data/ICV off.
*/
- if (ep - bp < sa->authlen) {
+ if (ep - ctptr < sa->authlen) {
nd_print_trunc(ndo);
return;
}
ep = ep - sa->authlen;
+ /*
+ * Calculate the length of the ciphertext. ep points to
+ * the beginning of the authentication data/integrity check
+ * value, i.e. right past the end of the ciphertext;
+ */
+ ctlen = ep - ctptr;
+
if (sa->evp == NULL)
return;
@@ -830,28 +835,17 @@ esp_print(netdissect_options *ndo,
"esp_print: can't allocate memory for cipher context");
}
- if (set_cipher_parameters(ctx, sa->evp, secret, NULL, 0) < 0) {
+ if (set_cipher_parameters(ctx, sa->evp, sa->secret, NULL, 0) < 0) {
(*ndo->ndo_warning)(ndo, "espkey init failed");
return;
}
- p = ivoff;
- if (set_cipher_parameters(ctx, NULL, NULL, p, 0) < 0) {
+ if (set_cipher_parameters(ctx, NULL, NULL, ivptr, 0) < 0) {
(*ndo->ndo_warning)(ndo, "IV init failed");
return;
}
/*
- * Calculate the length of the ciphertext. ep points to
- * the beginning of the authentication data/integrity check
- * value, i.e. right past the end of the ciphertext; p points
- * to the beginning of the payload, i.e. to the initialization
- * vector, so if we skip past the initialization vector, it
- * points to the beginning of the ciphertext.
- */
- ctlen = ep - (p + ivlen);
-
- /*
* Allocate buffers for the encrypted and decrypted
* data. Both buffers' sizes must be a multiple of
* the cipher block size, and the output buffer must
@@ -873,7 +867,7 @@ esp_print(netdissect_options *ndo,
* Copy the input data to the encrypted data buffer,
* and pad it with zeroes.
*/
- memcpy(input_buffer, p + ivlen, ctlen);
+ memcpy(input_buffer, ctptr, ctlen);
memset(input_buffer + ctlen, 0, buffer_size - ctlen);
/*
@@ -899,37 +893,23 @@ esp_print(netdissect_options *ndo,
* const buffer, but changing this would require a
* more complicated fix.
*/
- memcpy(p + ivlen, output_buffer, ctlen);
+ memcpy(ctptr, output_buffer, ctlen);
free(output_buffer);
- advance = ivoff - (const u_char *)esp + ivlen;
/*
- * Sanity check for pad length.
+ * Sanity check for pad length; if it, plus 2 for the pad
+ * length and next header fields, is bigger than the ciphertext
+ * length (which is also the plaintext length), it's too big.
*
* XXX - the check can fail if the packet is corrupt *or* if
* it was not decrypted with the correct key, so that the
* "plaintext" is not what was being sent.
*/
padlen = GET_U_1(ep - 2);
- if (ep - bp < padlen) {
- nd_print_trunc(ndo);
- return;
- }
-
- /*
- * Sanity check for payload length; +2 is for the pad length
- * and next header fields.
- *
- * XXX - the check can fail if the packet is corrupt *or* if
- * it was not decrypted with the correct key, so that the
- * "plaintext" is not what was being sent.
- */
- if (length <= advance + padlen + 2) {
+ if (padlen + 2 > ctlen) {
nd_print_trunc(ndo);
return;
}
- bp += advance;
- length -= advance + padlen + 2;
/* Get the next header */
nh = GET_U_1(ep - 1);
@@ -937,7 +917,8 @@ esp_print(netdissect_options *ndo,
ND_PRINT(": ");
/* Now print the payload. */
- ip_print_demux(ndo, bp, length, ver, fragmented, ttl_hl, nh, bp2);
+ ip_print_demux(ndo, ctptr, ctlen - (padlen + 2), ver, fragmented,
+ ttl_hl, nh, bp2);
#endif
}
#ifdef HAVE_LIBCRYPTO