diff -Nru openssl-1.0.2d/debian/changelog openssl-1.0.2d/debian/changelog --- openssl-1.0.2d/debian/changelog 2016-02-29 12:55:23.000000000 +0000 +++ openssl-1.0.2d/debian/changelog 2016-04-28 14:01:18.000000000 +0000 @@ -1,3 +1,33 @@ +openssl (1.0.2d-0ubuntu1.5) wily-security; urgency=medium + + * SECURITY UPDATE: EVP_EncodeUpdate overflow + - debian/patches/CVE-2016-2105.patch: properly check lengths in + crypto/evp/encode.c, add documentation to + doc/crypto/EVP_EncodeInit.pod, doc/crypto/evp.pod. + - CVE-2016-2105 + * SECURITY UPDATE: EVP_EncryptUpdate overflow + - debian/patches/CVE-2016-2106.patch: fix overflow in + crypto/evp/evp_enc.c. + - CVE-2016-2106 + * SECURITY UPDATE: Padding oracle in AES-NI CBC MAC check + - debian/patches/CVE-2016-2107.patch: check that there are enough + padding characters in crypto/evp/e_aes_cbc_hmac_sha1.c, + crypto/evp/e_aes_cbc_hmac_sha256.c. + - CVE-2016-2107 + * SECURITY UPDATE: Memory corruption in the ASN.1 encoder + - debian/patches/CVE-2016-2108.patch: fix ASN1_INTEGER handling in + crypto/asn1/a_type.c, crypto/asn1/asn1.h, crypto/asn1/tasn_dec.c, + crypto/asn1/tasn_enc.c. + - CVE-2016-2108 + * SECURITY UPDATE: ASN.1 BIO excessive memory allocation + - debian/patches/CVE-2016-2109.patch: properly handle large amounts of + data in crypto/asn1/a_d2i_fp.c. + - CVE-2016-2109 + * debian/patches/min_1024_dh_size.patch: change minimum DH size from 768 + to 1024. + + -- Marc Deslauriers Thu, 28 Apr 2016 10:00:31 -0400 + openssl (1.0.2d-0ubuntu1.4) wily-security; urgency=medium * SECURITY UPDATE: side channel attack on modular exponentiation diff -Nru openssl-1.0.2d/debian/patches/CVE-2016-2105.patch openssl-1.0.2d/debian/patches/CVE-2016-2105.patch --- openssl-1.0.2d/debian/patches/CVE-2016-2105.patch 1970-01-01 00:00:00.000000000 +0000 +++ openssl-1.0.2d/debian/patches/CVE-2016-2105.patch 2016-04-28 13:59:49.000000000 +0000 @@ -0,0 +1,219 @@ +Description: fix EVP_EncodeUpdate overflow +Origin: backport, 700daeecb890721176bd23effc4166221cdd0271 +Origin: backport, 29188216f818e5b34f3b17ee8ed31e8336f3817e +Origin: backport, f332816ef87556b7e89b98206c14df1f128b6d9f + +Index: openssl-1.0.2d/crypto/evp/encode.c +=================================================================== +--- openssl-1.0.2d.orig/crypto/evp/encode.c 2016-04-28 09:59:47.321944601 -0400 ++++ openssl-1.0.2d/crypto/evp/encode.c 2016-04-28 09:59:47.313944482 -0400 +@@ -134,13 +134,13 @@ + const unsigned char *in, int inl) + { + int i, j; +- unsigned int total = 0; ++ size_t total = 0; + + *outl = 0; + if (inl <= 0) + return; + OPENSSL_assert(ctx->length <= (int)sizeof(ctx->enc_data)); +- if ((ctx->num + inl) < ctx->length) { ++ if (ctx->length - ctx->num > inl) { + memcpy(&(ctx->enc_data[ctx->num]), in, inl); + ctx->num += inl; + return; +@@ -157,7 +157,7 @@ + *out = '\0'; + total = j + 1; + } +- while (inl >= ctx->length) { ++ while (inl >= ctx->length && total <= INT_MAX) { + j = EVP_EncodeBlock(out, in, ctx->length); + in += ctx->length; + inl -= ctx->length; +@@ -166,6 +166,11 @@ + *out = '\0'; + total += j + 1; + } ++ if (total > INT_MAX) { ++ /* Too much output data! */ ++ *outl = 0; ++ return; ++ } + if (inl != 0) + memcpy(&(ctx->enc_data[0]), in, inl); + ctx->num = inl; +Index: openssl-1.0.2d/doc/crypto/EVP_EncodeInit.pod +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ openssl-1.0.2d/doc/crypto/EVP_EncodeInit.pod 2016-04-28 09:59:47.317944542 -0400 +@@ -0,0 +1,145 @@ ++=pod ++ ++=head1 NAME ++ ++EVP_ENCODE_CTX_new, EVP_ENCODE_CTX_free, EVP_ENCODE_CTX_num, EVP_EncodeInit, ++EVP_EncodeUpdate, EVP_EncodeFinal, EVP_EncodeBlock, EVP_DecodeInit, ++EVP_DecodeUpdate, EVP_DecodeFinal, EVP_DecodeBlock - EVP base 64 encode/decode ++routines ++ ++=head1 SYNOPSIS ++ ++ #include ++ ++ EVP_ENCODE_CTX *EVP_ENCODE_CTX_new(void); ++ void EVP_ENCODE_CTX_free(EVP_ENCODE_CTX *ctx); ++ int EVP_ENCODE_CTX_num(EVP_ENCODE_CTX *ctx); ++ void EVP_EncodeInit(EVP_ENCODE_CTX *ctx); ++ void EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl, ++ const unsigned char *in, int inl); ++ void EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl); ++ int EVP_EncodeBlock(unsigned char *t, const unsigned char *f, int n); ++ ++ void EVP_DecodeInit(EVP_ENCODE_CTX *ctx); ++ int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl, ++ const unsigned char *in, int inl); ++ int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, unsigned ++ char *out, int *outl); ++ int EVP_DecodeBlock(unsigned char *t, const unsigned char *f, int n); ++ ++=head1 DESCRIPTION ++ ++The EVP encode routines provide a high level interface to base 64 encoding and ++decoding. Base 64 encoding converts binary data into a printable form that uses ++the characters A-Z, a-z, 0-9, "+" and "/" to represent the data. For every 3 ++bytes of binary data provided approximately 4 bytes of base 64 encoded data will ++be produced (see below). If the input data length is not a multiple of 3 then ++the output data will be padded at the end using the "=" character. ++ ++EVP_ENCODE_CTX_new() allocates, initializes and returns a context to be used for ++the encode/decode functions. ++ ++EVP_ENCODE_CTX_free() cleans up an encode/decode context B and frees up the ++space allocated to it. ++ ++Encoding of binary base 64 data is performed in blocks of 48 input bytes (or ++less for the final block). For each 48 byte input block encoded 64 bytes of base ++64 data is output plus an additional newline character (i.e. 65 bytes in total). ++The final block (which may be less than 48 bytes) will output 4 bytes for every ++3 bytes of input. If the data length is not divisible by 3 then a full 4 bytes ++is still output for the final 1 or 2 bytes of input. Similarly a newline ++character will also be output. ++ ++EVP_EncodeInit() initialises B for the start of a new encoding operation. ++ ++EVP_EncodeUpdate() encode B bytes of data found in the buffer pointed to by ++B. The output is stored in the buffer B and the number of bytes output ++is stored in B<*outl>. It is the caller's responsibility to ensure that the ++buffer at B is sufficiently large to accommodate the output data. Only full ++blocks of data (48 bytes) will be immediately processed and output by this ++function. Any remainder is held in the B object and will be processed by a ++subsequent call to EVP_EncodeUpdate() or EVP_EncodeFinal(). To calculate the ++required size of the output buffer add together the value of B with the ++amount of unprocessed data held in B and divide the result by 48 (ignore ++any remainder). This gives the number of blocks of data that will be processed. ++Ensure the output buffer contains 65 bytes of storage for each block, plus an ++additional byte for a NUL terminator. EVP_EncodeUpdate() may be called ++repeatedly to process large amounts of input data. In the event of an error ++EVP_EncodeUpdate() will set B<*outl> to 0. ++ ++EVP_EncodeFinal() must be called at the end of an encoding operation. It will ++process any partial block of data remaining in the B object. The output ++data will be stored in B and the length of the data written will be stored ++in B<*outl>. It is the caller's responsibility to ensure that B is ++sufficiently large to accommodate the output data which will never be more than ++65 bytes plus an additional NUL terminator (i.e. 66 bytes in total). ++ ++EVP_ENCODE_CTX_num() will return the number of as yet unprocessed bytes still to ++be encoded or decoded that are pending in the B object. ++ ++EVP_EncodeBlock() encodes a full block of input data in B and of length ++B and stores it in B. For every 3 bytes of input provided 4 bytes of ++output data will be produced. If B is not divisible by 3 then the block is ++encoded as a final block of data and the output is padded such that it is always ++divisible by 4. Additionally a NUL terminator character will be added. For ++example if 16 bytes of input data is provided then 24 bytes of encoded data is ++created plus 1 byte for a NUL terminator (i.e. 25 bytes in total). The length of ++the data generated I the NUL terminator is returned from the function. ++ ++EVP_DecodeInit() initialises B for the start of a new decoding operation. ++ ++EVP_DecodeUpdate() decodes B bytes of data found in the buffer pointed to ++by B. The output is stored in the buffer B and the number of bytes ++output is stored in B<*outl>. It is the caller's responsibility to ensure that ++the buffer at B is sufficiently large to accommodate the output data. This ++function will attempt to decode as much data as possible in 4 byte chunks. Any ++whitespace, newline or carriage return characters are ignored. Any partial chunk ++of unprocessed data (1, 2 or 3 bytes) that remains at the end will be held in ++the B object and processed by a subsequent call to EVP_DecodeUpdate(). If ++any illegal base 64 characters are encountered or if the base 64 padding ++character "=" is encountered in the middle of the data then the function returns ++-1 to indicate an error. A return value of 0 or 1 indicates successful ++processing of the data. A return value of 0 additionally indicates that the last ++input data characters processed included the base 64 padding character "=" and ++therefore no more non-padding character data is expected to be processed. For ++every 4 valid base 64 bytes processed (ignoring whitespace, carriage returns and ++line feeds), 3 bytes of binary output data will be produced (or less at the end ++of the data where the padding character "=" has been used). ++ ++EVP_DecodeFinal() must be called at the end of a decoding operation. If there ++is any unprocessed data still in B then the input data must not have been ++a multiple of 4 and therefore an error has occurred. The function will return -1 ++in this case. Otherwise the function returns 1 on success. ++ ++EVP_DecodeBlock() will decode the block of B bytes of base 64 data contained ++in B and store the result in B. Any leading whitespace will be trimmed as ++will any trailing whitespace, newlines, carriage returns or EOF characters. ++After such trimming the length of the data in B must be divisbile by 4. For ++every 4 input bytes exactly 3 output bytes will be produced. The output will be ++padded with 0 bits if necessary to ensure that the output is always 3 bytes for ++every 4 input bytes. This function will return the length of the data decoded or ++-1 on error. ++ ++=head1 RETURN VALUES ++ ++EVP_ENCODE_CTX_new() returns a pointer to the newly allocated EVP_ENCODE_CTX ++object or NULL on error. ++ ++EVP_ENCODE_CTX_num() returns the number of bytes pending encoding or decoding in ++B. ++ ++EVP_EncodeBlock() returns the number of bytes encoded excluding the NUL ++terminator. ++ ++EVP_DecodeUpdate() returns -1 on error and 0 or 1 on success. If 0 is returned ++then no more non-padding base 64 characters are expected. ++ ++EVP_DecodeFinal() returns -1 on error or 1 on success. ++ ++EVP_DecodeBlock() returns the length of the data decoded or -1 on error. ++ ++=head1 SEE ALSO ++ ++L ++ ++=cut +Index: openssl-1.0.2d/doc/crypto/evp.pod +=================================================================== +--- openssl-1.0.2d.orig/doc/crypto/evp.pod 2016-04-28 09:59:47.321944601 -0400 ++++ openssl-1.0.2d/doc/crypto/evp.pod 2016-04-28 09:59:47.317944542 -0400 +@@ -63,6 +63,10 @@ + + Algorithms are loaded with L. + ++The LI<...>|EVP_EncodeInit(3)> and ++LI<...>|EVP_EncodeInit(3)> functions implement base 64 encoding ++and decoding. ++ + All the symmetric algorithms (ciphers), digests and asymmetric algorithms + (public key algorithms) can be replaced by L modules providing alternative + implementations. If ENGINE implementations of ciphers or digests are registered +@@ -85,6 +89,7 @@ + L, + L, + L, ++L, + L, + L, + L, diff -Nru openssl-1.0.2d/debian/patches/CVE-2016-2106.patch openssl-1.0.2d/debian/patches/CVE-2016-2106.patch --- openssl-1.0.2d/debian/patches/CVE-2016-2106.patch 1970-01-01 00:00:00.000000000 +0000 +++ openssl-1.0.2d/debian/patches/CVE-2016-2106.patch 2016-04-28 13:59:56.000000000 +0000 @@ -0,0 +1,57 @@ +From 3e17fe7e40ed2eeb4f0892d376ac40d279780aa9 Mon Sep 17 00:00:00 2001 +From: Matt Caswell +Date: Thu, 3 Mar 2016 23:36:23 +0000 +Subject: [PATCH] Fix encrypt overflow + +An overflow can occur in the EVP_EncryptUpdate function. If an attacker is +able to supply very large amounts of input data after a previous call to +EVP_EncryptUpdate with a partial block then a length check can overflow +resulting in a heap corruption. + +Following an analysis of all OpenSSL internal usage of the +EVP_EncryptUpdate function all usage is one of two forms. + +The first form is like this: +EVP_EncryptInit() +EVP_EncryptUpdate() + +i.e. where the EVP_EncryptUpdate() call is known to be the first called +function after an EVP_EncryptInit(), and therefore that specific call +must be safe. + +The second form is where the length passed to EVP_EncryptUpdate() can be +seen from the code to be some small value and therefore there is no +possibility of an overflow. + +Since all instances are one of these two forms, I believe that there can +be no overflows in internal code due to this problem. + +It should be noted that EVP_DecryptUpdate() can call EVP_EncryptUpdate() +in certain code paths. Also EVP_CipherUpdate() is a synonym for +EVP_EncryptUpdate(). Therefore I have checked all instances of these +calls too, and came to the same conclusion, i.e. there are no instances +in internal usage where an overflow could occur. + +This could still represent a security issue for end user code that calls +this function directly. + +CVE-2016-2106 + +Issue reported by Guido Vranken. +--- + crypto/evp/evp_enc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: openssl-1.0.2d/crypto/evp/evp_enc.c +=================================================================== +--- openssl-1.0.2d.orig/crypto/evp/evp_enc.c 2016-04-28 09:59:53.786041149 -0400 ++++ openssl-1.0.2d/crypto/evp/evp_enc.c 2016-04-28 09:59:53.782041090 -0400 +@@ -347,7 +347,7 @@ + bl = ctx->cipher->block_size; + OPENSSL_assert(bl <= (int)sizeof(ctx->buf)); + if (i != 0) { +- if (i + inl < bl) { ++ if (bl - i > inl) { + memcpy(&(ctx->buf[i]), in, inl); + ctx->buf_len += inl; + *outl = 0; diff -Nru openssl-1.0.2d/debian/patches/CVE-2016-2107.patch openssl-1.0.2d/debian/patches/CVE-2016-2107.patch --- openssl-1.0.2d/debian/patches/CVE-2016-2107.patch 1970-01-01 00:00:00.000000000 +0000 +++ openssl-1.0.2d/debian/patches/CVE-2016-2107.patch 2016-04-28 14:00:04.000000000 +0000 @@ -0,0 +1,55 @@ +Backport of: + +From 9e79d38892dc30c874934e0aef7409d31d4bf37f Mon Sep 17 00:00:00 2001 +From: Kurt Roeckx +Date: Sat, 16 Apr 2016 23:08:56 +0200 +Subject: [PATCH] Check that we have enough padding characters. + +CVE-2016-2107 +--- + crypto/evp/e_aes_cbc_hmac_sha1.c | 3 +++ + crypto/evp/e_aes_cbc_hmac_sha256.c | 3 +++ + 2 files changed, 6 insertions(+), 0 deletions(-) + +Index: openssl-1.0.2d/crypto/evp/e_aes_cbc_hmac_sha1.c +=================================================================== +--- openssl-1.0.2d.orig/crypto/evp/e_aes_cbc_hmac_sha1.c 2016-04-28 10:00:01.938162903 -0400 ++++ openssl-1.0.2d/crypto/evp/e_aes_cbc_hmac_sha1.c 2016-04-28 10:00:01.934162843 -0400 +@@ -60,6 +60,7 @@ + # include + # include + # include "modes_lcl.h" ++# include "constant_time_locl.h" + + # ifndef EVP_CIPH_FLAG_AEAD_CIPHER + # define EVP_CIPH_FLAG_AEAD_CIPHER 0x200000 +@@ -578,6 +579,8 @@ + maxpad |= (255 - maxpad) >> (sizeof(maxpad) * 8 - 8); + maxpad &= 255; + ++ ret &= constant_time_ge(maxpad, pad); ++ + inp_len = len - (SHA_DIGEST_LENGTH + pad + 1); + mask = (0 - ((inp_len - len) >> (sizeof(inp_len) * 8 - 1))); + inp_len &= mask; +Index: openssl-1.0.2d/crypto/evp/e_aes_cbc_hmac_sha256.c +=================================================================== +--- openssl-1.0.2d.orig/crypto/evp/e_aes_cbc_hmac_sha256.c 2016-04-28 10:00:01.938162903 -0400 ++++ openssl-1.0.2d/crypto/evp/e_aes_cbc_hmac_sha256.c 2016-04-28 10:00:01.934162843 -0400 +@@ -60,6 +60,7 @@ + # include + # include + # include "modes_lcl.h" ++# include "constant_time_locl.h" + + # ifndef EVP_CIPH_FLAG_AEAD_CIPHER + # define EVP_CIPH_FLAG_AEAD_CIPHER 0x200000 +@@ -578,6 +579,8 @@ + maxpad |= (255 - maxpad) >> (sizeof(maxpad) * 8 - 8); + maxpad &= 255; + ++ ret &= constant_time_ge(maxpad, pad); ++ + inp_len = len - (SHA256_DIGEST_LENGTH + pad + 1); + mask = (0 - ((inp_len - len) >> (sizeof(inp_len) * 8 - 1))); + inp_len &= mask; diff -Nru openssl-1.0.2d/debian/patches/CVE-2016-2108.patch openssl-1.0.2d/debian/patches/CVE-2016-2108.patch --- openssl-1.0.2d/debian/patches/CVE-2016-2108.patch 1970-01-01 00:00:00.000000000 +0000 +++ openssl-1.0.2d/debian/patches/CVE-2016-2108.patch 2016-04-28 14:00:11.000000000 +0000 @@ -0,0 +1,91 @@ +Description: fix Memory corruption in the ASN.1 encoder +Origin: backport, c5e4bc81c5a142cab7f46f69824fa35367999ee8 +Origin: backport, ddf29e9b413a12b778ae39d3682b99da201540b1 + +Index: openssl-1.0.2d/crypto/asn1/a_type.c +=================================================================== +--- openssl-1.0.2d.orig/crypto/asn1/a_type.c 2016-04-28 10:00:09.006268460 -0400 ++++ openssl-1.0.2d/crypto/asn1/a_type.c 2016-04-28 10:00:08.998268340 -0400 +@@ -126,9 +126,7 @@ + result = 0; /* They do not have content. */ + break; + case V_ASN1_INTEGER: +- case V_ASN1_NEG_INTEGER: + case V_ASN1_ENUMERATED: +- case V_ASN1_NEG_ENUMERATED: + case V_ASN1_BIT_STRING: + case V_ASN1_OCTET_STRING: + case V_ASN1_SEQUENCE: +Index: openssl-1.0.2d/crypto/asn1/asn1.h +=================================================================== +--- openssl-1.0.2d.orig/crypto/asn1/asn1.h 2016-04-28 10:00:09.006268460 -0400 ++++ openssl-1.0.2d/crypto/asn1/asn1.h 2016-04-28 10:00:08.998268340 -0400 +@@ -96,13 +96,11 @@ + # define V_ASN1_OTHER -3/* used in ASN1_TYPE */ + # define V_ASN1_ANY -4/* used in ASN1 template code */ + +-# define V_ASN1_NEG 0x100/* negative flag */ +- + # define V_ASN1_UNDEF -1 ++/* ASN.1 tag values */ + # define V_ASN1_EOC 0 + # define V_ASN1_BOOLEAN 1 /**/ + # define V_ASN1_INTEGER 2 +-# define V_ASN1_NEG_INTEGER (2 | V_ASN1_NEG) + # define V_ASN1_BIT_STRING 3 + # define V_ASN1_OCTET_STRING 4 + # define V_ASN1_NULL 5 +@@ -111,7 +109,6 @@ + # define V_ASN1_EXTERNAL 8 + # define V_ASN1_REAL 9 + # define V_ASN1_ENUMERATED 10 +-# define V_ASN1_NEG_ENUMERATED (10 | V_ASN1_NEG) + # define V_ASN1_UTF8STRING 12 + # define V_ASN1_SEQUENCE 16 + # define V_ASN1_SET 17 +@@ -129,6 +126,17 @@ + # define V_ASN1_GENERALSTRING 27 /**/ + # define V_ASN1_UNIVERSALSTRING 28 /**/ + # define V_ASN1_BMPSTRING 30 ++ ++/* ++ * NB the constants below are used internally by ASN1_INTEGER ++ * and ASN1_ENUMERATED to indicate the sign. They are *not* on ++ * the wire tag values. ++ */ ++ ++# define V_ASN1_NEG 0x100 ++# define V_ASN1_NEG_INTEGER (2 | V_ASN1_NEG) ++# define V_ASN1_NEG_ENUMERATED (10 | V_ASN1_NEG) ++ + /* For use with d2i_ASN1_type_bytes() */ + # define B_ASN1_NUMERICSTRING 0x0001 + # define B_ASN1_PRINTABLESTRING 0x0002 +Index: openssl-1.0.2d/crypto/asn1/tasn_dec.c +=================================================================== +--- openssl-1.0.2d.orig/crypto/asn1/tasn_dec.c 2016-04-28 10:00:09.006268460 -0400 ++++ openssl-1.0.2d/crypto/asn1/tasn_dec.c 2016-04-28 10:00:08.998268340 -0400 +@@ -903,9 +903,7 @@ + break; + + case V_ASN1_INTEGER: +- case V_ASN1_NEG_INTEGER: + case V_ASN1_ENUMERATED: +- case V_ASN1_NEG_ENUMERATED: + tint = (ASN1_INTEGER **)pval; + if (!c2i_ASN1_INTEGER(tint, &cont, len)) + goto err; +Index: openssl-1.0.2d/crypto/asn1/tasn_enc.c +=================================================================== +--- openssl-1.0.2d.orig/crypto/asn1/tasn_enc.c 2016-04-28 10:00:09.006268460 -0400 ++++ openssl-1.0.2d/crypto/asn1/tasn_enc.c 2016-04-28 10:00:08.998268340 -0400 +@@ -611,9 +611,7 @@ + break; + + case V_ASN1_INTEGER: +- case V_ASN1_NEG_INTEGER: + case V_ASN1_ENUMERATED: +- case V_ASN1_NEG_ENUMERATED: + /* + * These are all have the same content format as ASN1_INTEGER + */ diff -Nru openssl-1.0.2d/debian/patches/CVE-2016-2109.patch openssl-1.0.2d/debian/patches/CVE-2016-2109.patch --- openssl-1.0.2d/debian/patches/CVE-2016-2109.patch 1970-01-01 00:00:00.000000000 +0000 +++ openssl-1.0.2d/debian/patches/CVE-2016-2109.patch 2016-04-28 14:00:14.000000000 +0000 @@ -0,0 +1,87 @@ +Backport of: + +From c62981390d6cf9e3d612c489b8b77c2913b25807 Mon Sep 17 00:00:00 2001 +From: "Dr. Stephen Henson" +Date: Mon, 11 Apr 2016 13:57:20 +0100 +Subject: [PATCH] Harden ASN.1 BIO handling of large amounts of data. + +If the ASN.1 BIO is presented with a large length field read it in +chunks of increasing size checking for EOF on each read. This prevents +small files allocating excessive amounts of data. + +CVE-2016-2109 + +Thanks to Brian Carpenter for reporting this issue. + +Reviewed-by: Viktor Dukhovni +--- + crypto/asn1/a_d2i_fp.c | 36 ++++++++++++++++++++++++++---------- + 1 file changed, 26 insertions(+), 10 deletions(-) + +Index: openssl-1.0.2d/crypto/asn1/a_d2i_fp.c +=================================================================== +--- openssl-1.0.2d.orig/crypto/asn1/a_d2i_fp.c 2016-04-28 08:45:39.255414005 -0400 ++++ openssl-1.0.2d/crypto/asn1/a_d2i_fp.c 2016-04-28 08:45:39.251413945 -0400 +@@ -141,6 +141,7 @@ + #endif + + #define HEADER_SIZE 8 ++#define ASN1_CHUNK_INITIAL_SIZE (16 * 1024) + static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb) + { + BUF_MEM *b; +@@ -217,29 +218,44 @@ + /* suck in c.slen bytes of data */ + want = c.slen; + if (want > (len - off)) { ++ size_t chunk_max = ASN1_CHUNK_INITIAL_SIZE; ++ + want -= (len - off); + if (want > INT_MAX /* BIO_read takes an int length */ || + len + want < len) { + ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_TOO_LONG); + goto err; + } +- if (!BUF_MEM_grow_clean(b, len + want)) { +- ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ERR_R_MALLOC_FAILURE); +- goto err; +- } + while (want > 0) { +- i = BIO_read(in, &(b->data[len]), want); +- if (i <= 0) { +- ASN1err(ASN1_F_ASN1_D2I_READ_BIO, +- ASN1_R_NOT_ENOUGH_DATA); ++ /* ++ * Read content in chunks of increasing size ++ * so we can return an error for EOF without ++ * having to allocate the entire content length ++ * in one go. ++ */ ++ size_t chunk = want > chunk_max ? chunk_max : want; ++ ++ if (!BUF_MEM_grow_clean(b, len + chunk)) { ++ ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ERR_R_MALLOC_FAILURE); + goto err; + } ++ want -= chunk; ++ while (chunk > 0) { ++ i = BIO_read(in, &(b->data[len]), chunk); ++ if (i <= 0) { ++ ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ++ ASN1_R_NOT_ENOUGH_DATA); ++ goto err; ++ } + /* + * This can't overflow because |len+want| didn't + * overflow. + */ +- len += i; +- want -= i; ++ len += i; ++ chunk -= i; ++ } ++ if (chunk_max < INT_MAX/2) ++ chunk_max *= 2; + } + } + if (off + c.slen < off) { diff -Nru openssl-1.0.2d/debian/patches/min_1024_dh_size.patch openssl-1.0.2d/debian/patches/min_1024_dh_size.patch --- openssl-1.0.2d/debian/patches/min_1024_dh_size.patch 1970-01-01 00:00:00.000000000 +0000 +++ openssl-1.0.2d/debian/patches/min_1024_dh_size.patch 2016-04-28 14:00:29.000000000 +0000 @@ -0,0 +1,24 @@ +From a4530ce0398d673b25a15b72a18dee1d8b14c07d Mon Sep 17 00:00:00 2001 +From: Kurt Roeckx +Date: Sun, 10 Jan 2016 13:55:08 +0100 +Subject: [PATCH] Change minimum DH size from 768 to 1024 + +Reviewed-by: Viktor Dukhovni +--- + CHANGES | 3 ++- + ssl/s3_clnt.c | 2 +- + 2 files changed, 3 insertions(+), 2 deletions(-) + +Index: openssl-1.0.2d/ssl/s3_clnt.c +=================================================================== +--- openssl-1.0.2d.orig/ssl/s3_clnt.c 2016-04-28 10:00:26.870535218 -0400 ++++ openssl-1.0.2d/ssl/s3_clnt.c 2016-04-28 10:00:26.866535159 -0400 +@@ -3565,7 +3565,7 @@ + DH_free(dh_srvr); + } + +- if ((!SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && dh_size < 768) ++ if ((!SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && dh_size < 1024) + || (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && dh_size < 512)) { + SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, SSL_R_DH_KEY_TOO_SMALL); + goto f_err; diff -Nru openssl-1.0.2d/debian/patches/series openssl-1.0.2d/debian/patches/series --- openssl-1.0.2d/debian/patches/series 2016-02-26 17:47:02.000000000 +0000 +++ openssl-1.0.2d/debian/patches/series 2016-04-28 14:00:25.000000000 +0000 @@ -26,3 +26,9 @@ CVE-2016-0799.patch CVE-2016-0797.patch CVE-2016-0702.patch +CVE-2016-2105.patch +CVE-2016-2106.patch +CVE-2016-2107.patch +CVE-2016-2108.patch +CVE-2016-2109.patch +min_1024_dh_size.patch