]> The Tcpdump Group git mirrors - tcpdump/commitdiff
Encrypted data buffer sizes must also be a multiple of the cipher block size.
authorGuy Harris <[email protected]>
Thu, 24 May 2018 18:45:19 +0000 (11:45 -0700)
committerGuy Harris <[email protected]>
Sat, 24 Nov 2018 02:55:56 +0000 (18:55 -0800)
This should address the issue in GitHub pull request #680.

(cherry picked from commit 4ba56b8c2e1240e2526db357c3d8bed4e9777bad)

print-esp.c

index fae1e71ff750dc00f6b5f8489224c8d7cb011385..bc38c6f7453530bea59759033c7eaaed4eceebe3 100644 (file)
@@ -191,8 +191,8 @@ int esp_print_decrypt_buffer_by_ikev2(netdissect_options *ndo,
        const u_char *iv;
        unsigned int len;
        EVP_CIPHER_CTX *ctx;
-       unsigned int block_size, output_buffer_size;
-       u_char *output_buffer;
+       unsigned int block_size, buffer_size;
+       u_char *input_buffer, *output_buffer;
 
        /* initiator arg is any non-zero value */
        if(initiator) initiator=1;
@@ -227,19 +227,41 @@ int esp_print_decrypt_buffer_by_ikev2(netdissect_options *ndo,
                (*ndo->ndo_warning)(ndo, "espkey init failed");
        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
-        * its size must be a multiple of the cipher block size.
+        * 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 be separate from the input
+        * buffer.
         */
        block_size = (unsigned int)EVP_CIPHER_CTX_block_size(ctx);
-       output_buffer_size = len + (block_size - len % block_size);
-       output_buffer = (u_char *)malloc(output_buffer_size);
+       buffer_size = len + (block_size - len % block_size);
+
+       /*
+        * Attempt to allocate the input buffer.
+        */
+       input_buffer = (u_char *)malloc(buffer_size);
+       if (input_buffer == NULL) {
+               (*ndo->ndo_warning)(ndo, "can't allocate memory for encrypted data buffer");
+               EVP_CIPHER_CTX_free(ctx);
+               return 0;
+       }
+       /*
+        * Copy the input data to the encrypted data buffer, and pad it
+        * with zeroes.
+        */
+       memcpy(input_buffer, buf, len);
+       memset(input_buffer + len, 0, buffer_size - len);
+
+       /*
+        * Attempt to allocate the output buffer.
+        */
+       output_buffer = (u_char *)malloc(buffer_size);
        if (output_buffer == NULL) {
                (*ndo->ndo_warning)(ndo, "can't allocate memory for decryption buffer");
+               free(input_buffer);
                EVP_CIPHER_CTX_free(ctx);
                return 0;
        }
-       EVP_Cipher(ctx, output_buffer, buf, len);
+       EVP_Cipher(ctx, output_buffer, input_buffer, len);
        EVP_CIPHER_CTX_free(ctx);
 
        /*
@@ -247,6 +269,7 @@ int esp_print_decrypt_buffer_by_ikev2(netdissect_options *ndo,
         * but changing this would require a more complicated fix.
         */
        memcpy(buf, output_buffer, len);
+       free(input_buffer);
        free(output_buffer);
 
        ndo->ndo_packetp = buf;
@@ -664,8 +687,8 @@ esp_print(netdissect_options *ndo,
        const u_char *ivoff;
        const u_char *p;
        EVP_CIPHER_CTX *ctx;
-       unsigned int block_size, output_buffer_size;
-       u_char *output_buffer;
+       unsigned int block_size, buffer_size;
+       u_char *input_buffer, *output_buffer;
 #endif
 
        esp = (const struct newesp *)bp;
@@ -781,21 +804,43 @@ esp_print(netdissect_options *ndo,
                        len = ep - (p + ivlen);
 
                        /*
-                        * Allocate a buffer for the decrypted data.
-                        * The output buffer must be separate from the
-                        * input buffer, and its size must be a multiple
-                        * of the cipher block size.
+                        * 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
+                        * be separate from the input buffer.
                         */
                        block_size = (unsigned int)EVP_CIPHER_CTX_block_size(ctx);
-                       output_buffer_size = len + (block_size - len % block_size);
-                       output_buffer = (u_char *)malloc(output_buffer_size);
+                       buffer_size = len + (block_size - len % block_size);
+
+                       /*
+                        * Attempt to allocate the input buffer.
+                        */
+                       input_buffer = (u_char *)malloc(buffer_size);
+                       if (input_buffer == NULL) {
+                               (*ndo->ndo_warning)(ndo, "can't allocate memory for encrypted data buffer");
+                               EVP_CIPHER_CTX_free(ctx);
+                               return 0;
+                       }
+                       /*
+                        * Copy the input data to the encrypted data buffer,
+                        * and pad it with zeroes.
+                        */
+                       memcpy(input_buffer, p + ivlen, len);
+                       memset(input_buffer + len, 0, buffer_size - len);
+
+                       /*
+                        * Attempt to allocate the output buffer.
+                        */
+                       output_buffer = (u_char *)malloc(buffer_size);
                        if (output_buffer == NULL) {
                                (*ndo->ndo_warning)(ndo, "can't allocate memory for decryption buffer");
+                               free(input_buffer);
                                EVP_CIPHER_CTX_free(ctx);
                                return -1;
                        }
 
-                       EVP_Cipher(ctx, output_buffer, p + ivlen, len);
+                       EVP_Cipher(ctx, output_buffer, input_buffer, len);
+                       free(input_buffer);
                        EVP_CIPHER_CTX_free(ctx);
                        /*
                         * XXX - of course this is wrong, because buf is a