VYPR
Moderate severityNVD Advisory· Published Jun 4, 2018· Updated Aug 6, 2024

CVE-2016-1000345

CVE-2016-1000345

Description

In the Bouncy Castle JCE Provider version 1.55 and earlier the DHIES/ECIES CBC mode vulnerable to padding oracle attack. For BC 1.55 and older, in an environment where timings can be easily observed, it is possible with enough observations to identify when the decryption is failing due to padding.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Bouncy Castle JCE Provider 1.55 and earlier DHIES/ECIES CBC mode is vulnerable to a padding oracle attack, allowing plaintext recovery.

Vulnerability

In the Bouncy Castle JCE Provider versions 1.55 and earlier, the DHIES/ECIES implementation uses CBC mode without adequate protection against padding oracle attacks [1][2][3][4]. The decryption process leaks information through observable timing differences when padding validation fails, enabling an attacker to determine whether decryption of a chosen ciphertext is failing due to incorrect padding [4].

Exploitation

An attacker with the ability to capture ciphertexts and observe timing (oracle) can submit modified ciphertexts to a system that decrypts them using the affected implementation [4]. Repeated observations allow the attacker to deduce plaintext bytes by analyzing the decryption success or failure based on timing [4]. No authentication is required, only network access to the decryption endpoint.

Impact

Successful exploitation enables an attacker to recover the plaintext of encrypted messages without knowledge of the private key [3][4]. The confidentiality of data encrypted using DHIES/ECIES with CBC mode is compromised. The attacker gains plaintext disclosure, with no privilege escalation or remote code execution.

Mitigation

Upgrade to Bouncy Castle JCE Provider version 1.56 or later, which fixes the CBC padding oracle vulnerability [4]. Red Hat Satellite 6.4 and Red Hat Fuse 7.1 updates include fixed versions [1][2]. Ubuntu 14.04 LTS uses version 1.49+dfsg-2ubuntu0.1 [3]. No EOL or KEV listing identified. If patching is not possible, avoid using the affected DHIES/ECIES CBC mode.

AI Insight generated on May 22, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
org.bouncycastle:bcprov-jdk14Maven
< 1.561.56
org.bouncycastle:bcprov-jdk15Maven
< 1.561.56
org.bouncycastle:bcprov-jdk15onMaven
< 1.561.56

Affected products

4

Patches

1
21dcb3d9744c

modified IESEngine so that MAC check is the primary one

https://github.com/bcgit/bc-javaDavid HookAug 27, 2016via ghsa
7 files changed · +96 28
  • core/src/main/java/org/bouncycastle/crypto/engines/IESEngine.java+20 12 modified
    @@ -67,8 +67,8 @@ public IESEngine(
     
     
         /**
    -     * set up for use in conjunction with a block cipher to handle the
    -     * message.
    +     * Set up for use in conjunction with a block cipher to handle the
    +     * message.It is <b>strongly</b> recommended that the cipher is not in ECB mode.
          *
          * @param agree  the key agreement used as the basis for the encryption
          * @param kdf    the key derivation function used for byte generation
    @@ -269,15 +269,16 @@ private byte[] decryptBlock(
             int inLen)
             throws InvalidCipherTextException
         {
    -        byte[] M = null, K = null, K1 = null, K2 = null;
    -        int len;
    +        byte[] M, K, K1, K2;
    +        int len = 0;
     
             // Ensure that the length of the input is greater than the MAC in bytes
             if (inLen < V.length + mac.getMacSize())
             {
                 throw new InvalidCipherTextException("Length of input must be greater than the MAC and V combined");
             }
     
    +        // note order is important: set up keys, do simple encryptions, check mac, do final encryption.
             if (cipher == null)
             {
                 // Streaming mode.
    @@ -298,14 +299,13 @@ private byte[] decryptBlock(
                     System.arraycopy(K, K1.length, K2, 0, K2.length);
                 }
     
    +            // process the message
                 M = new byte[K1.length];
     
                 for (int i = 0; i != K1.length; i++)
                 {
                     M[i] = (byte)(in_enc[inOff + V.length + i] ^ K1[i]);
                 }
    -
    -            len = K1.length;
             }
             else
             {
    @@ -325,15 +325,15 @@ private byte[] decryptBlock(
                 }
                 else
                 {
    -                cipher.init(false, new KeyParameter(K1));    
    +                cipher.init(false, new KeyParameter(K1));
                 }
     
                 M = new byte[cipher.getOutputSize(inLen - V.length - mac.getMacSize())];
    +
    +            // do initial processing
                 len = cipher.processBytes(in_enc, inOff + V.length, inLen - V.length - mac.getMacSize(), M, 0);
    -            len += cipher.doFinal(M, len);
             }
     
    -
             // Convert the length of the encoding vector into a byte array.
             byte[] P2 = param.getEncodingV();
             byte[] L2 = null;
    @@ -362,11 +362,19 @@ private byte[] decryptBlock(
     
             if (!Arrays.constantTimeAreEqual(T1, T2))
             {
    -            throw new InvalidCipherTextException("Invalid MAC.");
    +            throw new InvalidCipherTextException("invalid MAC");
             }
     
    -        // Output the message.
    -        return Arrays.copyOfRange(M, 0, len);
    +        if (cipher == null)
    +        {
    +            return M;
    +        }
    +        else
    +        {
    +            len += cipher.doFinal(M, len);
    +
    +            return Arrays.copyOfRange(M, 0, len);
    +        }
         }
     
     
    
  • prov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/IESCipher.java+4 3 modified
    @@ -45,6 +45,7 @@
     import org.bouncycastle.crypto.parsers.DHIESPublicKeyParser;
     import org.bouncycastle.jcajce.provider.asymmetric.util.DHUtil;
     import org.bouncycastle.jcajce.provider.asymmetric.util.IESUtil;
    +import org.bouncycastle.jcajce.provider.util.BadBlockException;
     import org.bouncycastle.jcajce.util.BCJcaJceHelper;
     import org.bouncycastle.jcajce.util.JcaJceHelper;
     import org.bouncycastle.jce.interfaces.IESKey;
    @@ -425,7 +426,7 @@ public byte[] engineDoFinal(
                 }
                 catch (Exception e)
                 {
    -                throw new BadPaddingException(e.getMessage());
    +                throw new BadBlockException("unable to process block", e);
                 }
             }
     
    @@ -464,7 +465,7 @@ public byte[] getEncoded(AsymmetricKeyParameter keyParameter)
                 }
                 catch (Exception e)
                 {
    -                throw new BadPaddingException(e.getMessage());
    +                throw new BadBlockException("unable to process block", e);
                 }
             }
             else if (state == Cipher.DECRYPT_MODE || state == Cipher.UNWRAP_MODE)
    @@ -478,7 +479,7 @@ else if (state == Cipher.DECRYPT_MODE || state == Cipher.UNWRAP_MODE)
                 }
                 catch (InvalidCipherTextException e)
                 {
    -                throw new BadPaddingException(e.getMessage());
    +                throw new BadBlockException("unable to process block", e);
                 }
             }
             else
    
  • prov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/IESCipher.java+5 5 modified
    @@ -43,6 +43,7 @@
     import org.bouncycastle.crypto.parsers.ECIESPublicKeyParser;
     import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil;
     import org.bouncycastle.jcajce.provider.asymmetric.util.IESUtil;
    +import org.bouncycastle.jcajce.provider.util.BadBlockException;
     import org.bouncycastle.jcajce.util.BCJcaJceHelper;
     import org.bouncycastle.jcajce.util.JcaJceHelper;
     import org.bouncycastle.jce.interfaces.ECKey;
    @@ -430,7 +431,7 @@ public byte[] engineDoFinal(
                 }
                 catch (Exception e)
                 {
    -                throw new BadPaddingException(e.getMessage());
    +                throw new BadBlockException("unable to process block", e);
                 }
             }
     
    @@ -456,11 +457,10 @@ public byte[] getEncoded(AsymmetricKeyParameter keyParameter)
     
                     return engine.processBlock(in, 0, in.length);
                 }
    -            catch (Exception e)
    +            catch (final Exception e)
                 {
    -                throw new BadPaddingException(e.getMessage());
    +                throw new BadBlockException("unable to process block", e);
                 }
    -
             }
             else if (state == Cipher.DECRYPT_MODE || state == Cipher.UNWRAP_MODE)
             {
    @@ -473,7 +473,7 @@ else if (state == Cipher.DECRYPT_MODE || state == Cipher.UNWRAP_MODE)
                 }
                 catch (InvalidCipherTextException e)
                 {
    -                throw new BadPaddingException(e.getMessage());
    +                throw new BadBlockException("unable to process block", e);
                 }
             }
             else
    
  • prov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/CipherSpi.java+3 8 modified
    @@ -32,6 +32,7 @@
     import org.bouncycastle.crypto.engines.RSABlindedEngine;
     import org.bouncycastle.crypto.params.ParametersWithRandom;
     import org.bouncycastle.jcajce.provider.asymmetric.util.BaseCipherSpi;
    +import org.bouncycastle.jcajce.provider.util.BadBlockException;
     import org.bouncycastle.jcajce.provider.util.DigestFactory;
     import org.bouncycastle.jcajce.util.BCJcaJceHelper;
     import org.bouncycastle.jcajce.util.JcaJceHelper;
    @@ -528,15 +529,9 @@ private byte[] getOutput()
     
                 return cipher.processBlock(bytes, 0, bytes.length);
             }
    -        catch (final InvalidCipherTextException e)
    +        catch (InvalidCipherTextException e)
             {
    -            throw new BadPaddingException("unable to decrypt block")
    -            {
    -                public synchronized Throwable getCause()
    -                {
    -                    return e;
    -                }
    -            };
    +            throw new BadBlockException("unable to decrypt block", e);
             }
             finally
             {
    
  • prov/src/main/java/org/bouncycastle/jcajce/provider/util/BadBlockException.java+21 0 added
    @@ -0,0 +1,21 @@
    +package org.bouncycastle.jcajce.provider.util;
    +
    +import javax.crypto.BadPaddingException;
    +
    +public class BadBlockException
    +    extends BadPaddingException
    +{
    +    private final Throwable cause;
    +
    +    public BadBlockException(String msg, Throwable cause)
    +    {
    +        super(msg);
    +
    +        this.cause = cause;
    +    }
    +
    +    public Throwable getCause()
    +    {
    +        return cause;
    +    }
    +}
    
  • prov/src/test/java/org/bouncycastle/jce/provider/test/DHIESTest.java+22 0 modified
    @@ -7,6 +7,7 @@
     import java.security.SecureRandom;
     import java.security.Security;
     
    +import javax.crypto.BadPaddingException;
     import javax.crypto.Cipher;
     import javax.crypto.interfaces.DHPrivateKey;
     import javax.crypto.interfaces.DHPublicKey;
    @@ -222,6 +223,27 @@ public void doTest(
             out2 = c2.doFinal(out1, 0, out1.length);
             if (!areEqual(out2, message))
                 fail(testname + " test failed with non-null parameters, DHAES mode true.");
    +
    +        //
    +        // corrupted data test
    +        //
    +        byte[] tmp = new byte[out1.length];
    +        for (int i = 0; i != out1.length; i++)
    +        {
    +            System.arraycopy(out1, 0, tmp, 0, tmp.length);
    +            tmp[i] = (byte)~tmp[i];
    +
    +            try
    +            {
    +                c2.doFinal(tmp, 0, tmp.length);
    +
    +                fail("decrypted corrupted data");
    +            }
    +            catch (BadPaddingException e)
    +            {
    +                isTrue("wrong message: " + e.getMessage(), "unable to process block".equals(e.getMessage()));
    +            }
    +        }
         }
     
         public static void main(
    
  • prov/src/test/java/org/bouncycastle/jce/provider/test/ECIESTest.java+21 0 modified
    @@ -7,6 +7,7 @@
     import java.security.Security;
     import java.security.spec.ECGenParameterSpec;
     
    +import javax.crypto.BadPaddingException;
     import javax.crypto.Cipher;
     import javax.crypto.SealedObject;
     
    @@ -241,7 +242,27 @@ public void doTest(
             if (!areEqual(out2, message))
                 fail(testname + " test failed with non-null parameters, DHAES mode false.");
             
    +        //
    +        // corrupted data test
    +        //
    +        int offset = out1.length - (message.length + 8);
    +        byte[] tmp = new byte[out1.length];
    +        for (int i = offset; i != out1.length; i++)
    +        {
    +            System.arraycopy(out1, 0, tmp, 0, tmp.length);
    +            tmp[i] = (byte)~tmp[i];
    +
    +            try
    +            {
    +                c2.doFinal(tmp, 0, tmp.length);
     
    +                fail("decrypted corrupted data");
    +            }
    +            catch (BadPaddingException e)
    +            {
    +                isTrue("wrong message: " + e.getMessage(), "unable to process block".equals(e.getMessage()));
    +            }
    +        }
     // TODO: DHAES mode is not currently implemented, perhaps it shouldn't be...
     //        c1 = Cipher.getInstance(cipher + "/DHAES/PKCS7Padding","BC");
     //        c2 = Cipher.getInstance(cipher + "/DHAES/PKCS7Padding","BC");
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

11

News mentions

0

No linked articles in our index yet.