Skip to content

Commit 21dcb3d

Browse files
committed
modified IESEngine so that MAC check is the primary one
added general BadBlockException class for asymmetric ciphers.
1 parent 9385b0e commit 21dcb3d

File tree

7 files changed

+96
-28
lines changed

7 files changed

+96
-28
lines changed

core/src/main/java/org/bouncycastle/crypto/engines/IESEngine.java

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ public IESEngine(
6767

6868

6969
/**
70-
* set up for use in conjunction with a block cipher to handle the
71-
* message.
70+
* Set up for use in conjunction with a block cipher to handle the
71+
* message.It is <b>strongly</b> recommended that the cipher is not in ECB mode.
7272
*
7373
* @param agree the key agreement used as the basis for the encryption
7474
* @param kdf the key derivation function used for byte generation
@@ -269,15 +269,16 @@ private byte[] decryptBlock(
269269
int inLen)
270270
throws InvalidCipherTextException
271271
{
272-
byte[] M = null, K = null, K1 = null, K2 = null;
273-
int len;
272+
byte[] M, K, K1, K2;
273+
int len = 0;
274274

275275
// Ensure that the length of the input is greater than the MAC in bytes
276276
if (inLen < V.length + mac.getMacSize())
277277
{
278278
throw new InvalidCipherTextException("Length of input must be greater than the MAC and V combined");
279279
}
280280

281+
// note order is important: set up keys, do simple encryptions, check mac, do final encryption.
281282
if (cipher == null)
282283
{
283284
// Streaming mode.
@@ -298,14 +299,13 @@ private byte[] decryptBlock(
298299
System.arraycopy(K, K1.length, K2, 0, K2.length);
299300
}
300301

302+
// process the message
301303
M = new byte[K1.length];
302304

303305
for (int i = 0; i != K1.length; i++)
304306
{
305307
M[i] = (byte)(in_enc[inOff + V.length + i] ^ K1[i]);
306308
}
307-
308-
len = K1.length;
309309
}
310310
else
311311
{
@@ -325,15 +325,15 @@ private byte[] decryptBlock(
325325
}
326326
else
327327
{
328-
cipher.init(false, new KeyParameter(K1));
328+
cipher.init(false, new KeyParameter(K1));
329329
}
330330

331331
M = new byte[cipher.getOutputSize(inLen - V.length - mac.getMacSize())];
332+
333+
// do initial processing
332334
len = cipher.processBytes(in_enc, inOff + V.length, inLen - V.length - mac.getMacSize(), M, 0);
333-
len += cipher.doFinal(M, len);
334335
}
335336

336-
337337
// Convert the length of the encoding vector into a byte array.
338338
byte[] P2 = param.getEncodingV();
339339
byte[] L2 = null;
@@ -362,11 +362,19 @@ private byte[] decryptBlock(
362362

363363
if (!Arrays.constantTimeAreEqual(T1, T2))
364364
{
365-
throw new InvalidCipherTextException("Invalid MAC.");
365+
throw new InvalidCipherTextException("invalid MAC");
366366
}
367367

368-
// Output the message.
369-
return Arrays.copyOfRange(M, 0, len);
368+
if (cipher == null)
369+
{
370+
return M;
371+
}
372+
else
373+
{
374+
len += cipher.doFinal(M, len);
375+
376+
return Arrays.copyOfRange(M, 0, len);
377+
}
370378
}
371379

372380

prov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/IESCipher.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
import org.bouncycastle.crypto.parsers.DHIESPublicKeyParser;
4646
import org.bouncycastle.jcajce.provider.asymmetric.util.DHUtil;
4747
import org.bouncycastle.jcajce.provider.asymmetric.util.IESUtil;
48+
import org.bouncycastle.jcajce.provider.util.BadBlockException;
4849
import org.bouncycastle.jcajce.util.BCJcaJceHelper;
4950
import org.bouncycastle.jcajce.util.JcaJceHelper;
5051
import org.bouncycastle.jce.interfaces.IESKey;
@@ -425,7 +426,7 @@ public byte[] engineDoFinal(
425426
}
426427
catch (Exception e)
427428
{
428-
throw new BadPaddingException(e.getMessage());
429+
throw new BadBlockException("unable to process block", e);
429430
}
430431
}
431432

@@ -464,7 +465,7 @@ public byte[] getEncoded(AsymmetricKeyParameter keyParameter)
464465
}
465466
catch (Exception e)
466467
{
467-
throw new BadPaddingException(e.getMessage());
468+
throw new BadBlockException("unable to process block", e);
468469
}
469470
}
470471
else if (state == Cipher.DECRYPT_MODE || state == Cipher.UNWRAP_MODE)
@@ -478,7 +479,7 @@ else if (state == Cipher.DECRYPT_MODE || state == Cipher.UNWRAP_MODE)
478479
}
479480
catch (InvalidCipherTextException e)
480481
{
481-
throw new BadPaddingException(e.getMessage());
482+
throw new BadBlockException("unable to process block", e);
482483
}
483484
}
484485
else

prov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/IESCipher.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import org.bouncycastle.crypto.parsers.ECIESPublicKeyParser;
4444
import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil;
4545
import org.bouncycastle.jcajce.provider.asymmetric.util.IESUtil;
46+
import org.bouncycastle.jcajce.provider.util.BadBlockException;
4647
import org.bouncycastle.jcajce.util.BCJcaJceHelper;
4748
import org.bouncycastle.jcajce.util.JcaJceHelper;
4849
import org.bouncycastle.jce.interfaces.ECKey;
@@ -430,7 +431,7 @@ public byte[] engineDoFinal(
430431
}
431432
catch (Exception e)
432433
{
433-
throw new BadPaddingException(e.getMessage());
434+
throw new BadBlockException("unable to process block", e);
434435
}
435436
}
436437

@@ -456,11 +457,10 @@ public byte[] getEncoded(AsymmetricKeyParameter keyParameter)
456457

457458
return engine.processBlock(in, 0, in.length);
458459
}
459-
catch (Exception e)
460+
catch (final Exception e)
460461
{
461-
throw new BadPaddingException(e.getMessage());
462+
throw new BadBlockException("unable to process block", e);
462463
}
463-
464464
}
465465
else if (state == Cipher.DECRYPT_MODE || state == Cipher.UNWRAP_MODE)
466466
{
@@ -473,7 +473,7 @@ else if (state == Cipher.DECRYPT_MODE || state == Cipher.UNWRAP_MODE)
473473
}
474474
catch (InvalidCipherTextException e)
475475
{
476-
throw new BadPaddingException(e.getMessage());
476+
throw new BadBlockException("unable to process block", e);
477477
}
478478
}
479479
else

prov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/CipherSpi.java

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import org.bouncycastle.crypto.engines.RSABlindedEngine;
3333
import org.bouncycastle.crypto.params.ParametersWithRandom;
3434
import org.bouncycastle.jcajce.provider.asymmetric.util.BaseCipherSpi;
35+
import org.bouncycastle.jcajce.provider.util.BadBlockException;
3536
import org.bouncycastle.jcajce.provider.util.DigestFactory;
3637
import org.bouncycastle.jcajce.util.BCJcaJceHelper;
3738
import org.bouncycastle.jcajce.util.JcaJceHelper;
@@ -528,15 +529,9 @@ private byte[] getOutput()
528529

529530
return cipher.processBlock(bytes, 0, bytes.length);
530531
}
531-
catch (final InvalidCipherTextException e)
532+
catch (InvalidCipherTextException e)
532533
{
533-
throw new BadPaddingException("unable to decrypt block")
534-
{
535-
public synchronized Throwable getCause()
536-
{
537-
return e;
538-
}
539-
};
534+
throw new BadBlockException("unable to decrypt block", e);
540535
}
541536
finally
542537
{
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package org.bouncycastle.jcajce.provider.util;
2+
3+
import javax.crypto.BadPaddingException;
4+
5+
public class BadBlockException
6+
extends BadPaddingException
7+
{
8+
private final Throwable cause;
9+
10+
public BadBlockException(String msg, Throwable cause)
11+
{
12+
super(msg);
13+
14+
this.cause = cause;
15+
}
16+
17+
public Throwable getCause()
18+
{
19+
return cause;
20+
}
21+
}

prov/src/test/java/org/bouncycastle/jce/provider/test/DHIESTest.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import java.security.SecureRandom;
88
import java.security.Security;
99

10+
import javax.crypto.BadPaddingException;
1011
import javax.crypto.Cipher;
1112
import javax.crypto.interfaces.DHPrivateKey;
1213
import javax.crypto.interfaces.DHPublicKey;
@@ -222,6 +223,27 @@ public void doTest(
222223
out2 = c2.doFinal(out1, 0, out1.length);
223224
if (!areEqual(out2, message))
224225
fail(testname + " test failed with non-null parameters, DHAES mode true.");
226+
227+
//
228+
// corrupted data test
229+
//
230+
byte[] tmp = new byte[out1.length];
231+
for (int i = 0; i != out1.length; i++)
232+
{
233+
System.arraycopy(out1, 0, tmp, 0, tmp.length);
234+
tmp[i] = (byte)~tmp[i];
235+
236+
try
237+
{
238+
c2.doFinal(tmp, 0, tmp.length);
239+
240+
fail("decrypted corrupted data");
241+
}
242+
catch (BadPaddingException e)
243+
{
244+
isTrue("wrong message: " + e.getMessage(), "unable to process block".equals(e.getMessage()));
245+
}
246+
}
225247
}
226248

227249
public static void main(

prov/src/test/java/org/bouncycastle/jce/provider/test/ECIESTest.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import java.security.Security;
88
import java.security.spec.ECGenParameterSpec;
99

10+
import javax.crypto.BadPaddingException;
1011
import javax.crypto.Cipher;
1112
import javax.crypto.SealedObject;
1213

@@ -241,7 +242,27 @@ public void doTest(
241242
if (!areEqual(out2, message))
242243
fail(testname + " test failed with non-null parameters, DHAES mode false.");
243244

245+
//
246+
// corrupted data test
247+
//
248+
int offset = out1.length - (message.length + 8);
249+
byte[] tmp = new byte[out1.length];
250+
for (int i = offset; i != out1.length; i++)
251+
{
252+
System.arraycopy(out1, 0, tmp, 0, tmp.length);
253+
tmp[i] = (byte)~tmp[i];
254+
255+
try
256+
{
257+
c2.doFinal(tmp, 0, tmp.length);
244258

259+
fail("decrypted corrupted data");
260+
}
261+
catch (BadPaddingException e)
262+
{
263+
isTrue("wrong message: " + e.getMessage(), "unable to process block".equals(e.getMessage()));
264+
}
265+
}
245266
// TODO: DHAES mode is not currently implemented, perhaps it shouldn't be...
246267
// c1 = Cipher.getInstance(cipher + "/DHAES/PKCS7Padding","BC");
247268
// c2 = Cipher.getInstance(cipher + "/DHAES/PKCS7Padding","BC");

0 commit comments

Comments
 (0)