#endif
/*
- * this will adjust ndo_packetp and ndo_snapend to new buffer!
+ * This will allocate a new buffer containing the decrypted data.
+ * It returns 1 on success and 0 on failure.
+ *
+ * It will push the new buffer and the values of ndo->ndo_packetp and
+ * ndo->ndo_snapend onto the buffer stack, and change ndo->ndo_packetp
+ * and ndo->ndo_snapend to refer to the new buffer.
+ *
+ * Our caller must pop the buffer off the stack when it's finished
+ * dissecting anything in it and before it does any dissection of
+ * anything in the old buffer. That will free the new buffer.
*/
USES_APPLE_DEPRECATED_API
int esp_print_decrypt_buffer_by_ikev2(netdissect_options *ndo,
{
struct sa_list *sa;
const u_char *iv;
+ const u_char *ct;
unsigned int len;
EVP_CIPHER_CTX *ctx;
unsigned int block_size, buffer_size;
u_char *input_buffer, *output_buffer;
+ const u_char *pt;
/* initiator arg is any non-zero value */
if(initiator) initiator=1;
*/
end = end - sa->authlen;
iv = buf;
- buf = buf + sa->ivlen;
- len = end-buf;
+ ct = iv + sa->ivlen;
+ len = end-ct;
- if(end <= buf) return 0;
+ if(end <= ct) return 0;
ctx = EVP_CIPHER_CTX_new();
if (ctx == NULL)
* Copy the input data to the encrypted data buffer, and pad it
* with zeroes.
*/
- memcpy(input_buffer, buf, len);
+ memcpy(input_buffer, ct, len);
memset(input_buffer + len, 0, buffer_size - len);
/*
EVP_CIPHER_CTX_free(ctx);
/*
- * XXX - of course this is wrong, because buf is a const buffer,
- * but changing this would require a more complicated fix.
+ * Free the input buffer; we no longer need it.
*/
- memcpy(buf, output_buffer, len);
free(input_buffer);
- free(output_buffer);
- ndo->ndo_packetp = buf;
- ndo->ndo_snapend = end;
+ /*
+ * Get a pointer to the plaintext.
+ */
+ pt = output_buffer;
+
+ /*
+ * Switch to the output buffer for dissection, and save it
+ * on the buffer stack so it can be freed; our caller must
+ * pop it when done.
+ */
+ if (!nd_push_buffer(ndo, output_buffer, pt, pt + len)) {
+ free(output_buffer);
+ return 0;
+ }
return 1;
}
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 *iv;
u_int ivlen;
- const u_char *ivoff;
- const u_char *p;
+ const u_char *ct;
+ u_int ctlen;
EVP_CIPHER_CTX *ctx;
unsigned int block_size, buffer_size;
u_char *input_buffer, *output_buffer;
+ const u_char *pt;
+ u_int ptlen;
u_int padlen;
u_int nh;
#endif
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;
return;
/* pointer to the IV, if there is one */
- ivoff = (const u_char *)(esp + 1) + 0;
+ iv = (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.
+ */
+ ct = iv + 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 - ct < 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 - ct;
+
if (sa->evp == NULL)
return;
"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, iv, 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
* Copy the input data to the encrypted data buffer,
* and pad it with zeroes.
*/
- memcpy(input_buffer, p + ivlen, ctlen);
+ memcpy(input_buffer, ct, ctlen);
memset(input_buffer + ctlen, 0, buffer_size - ctlen);
/*
}
free(input_buffer);
EVP_CIPHER_CTX_free(ctx);
+
/*
- * XXX - of course this is wrong, because buf is a
- * const buffer, but changing this would require a
- * more complicated fix.
+ * Pointer to the plaintext.
*/
- memcpy(p + ivlen, output_buffer, ctlen);
- free(output_buffer);
- advance = ivoff - (const u_char *)esp + ivlen;
+ pt = output_buffer;
/*
- * Sanity check for pad length.
- *
- * 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.
+ * Length of the plaintext, which is the same as the length
+ * of the ciphertext.
*/
- padlen = GET_U_1(ep - 2);
- if (ep - bp < padlen) {
- nd_print_trunc(ndo);
- return;
+ ptlen = ctlen;
+
+ /*
+ * Switch to the output buffer for dissection, and
+ * save it on the buffer stack so it can be freed.
+ */
+ if (!nd_push_buffer(ndo, output_buffer, pt, pt + ctlen)) {
+ free(output_buffer);
+ (*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC,
+ "esp_print: can't push buffer on buffer stack");
}
+ ep = pt + ptlen;
/*
- * Sanity check for payload length; +2 is for the pad length
- * and next header fields.
+ * 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.
*/
- if (length <= advance + padlen + 2) {
+ padlen = GET_U_1(ep - 2);
+ if (padlen + 2 > ptlen) {
nd_print_trunc(ndo);
return;
}
- bp += advance;
- length -= advance + padlen + 2;
/* Get the next header */
nh = GET_U_1(ep - 1);
ND_PRINT(": ");
- /* Now print the payload. */
- ip_print_demux(ndo, bp, length, ver, fragmented, ttl_hl, nh, bp2);
+ /* Now dissect the plaintext. */
+ ip_print_demux(ndo, pt, ptlen - (padlen + 2), ver, fragmented,
+ ttl_hl, nh, bp2);
+
+ /* Pop the buffer, freeing it. */
+ nd_pop_buffer(ndo);
#endif
}
#ifdef HAVE_LIBCRYPTO