blob: d2f140578ef3e4df62088cd801c5ce031b11ea85 [file] [log] [blame]
package org.bouncycastle.jce.provider.test;
import java.io.IOException;
import java.security.AlgorithmParameters;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Security;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.asn1.cms.GCMParameters;
import org.bouncycastle.jcajce.spec.RepeatedSecretKeySpec;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.encoders.Hex;
import org.bouncycastle.util.test.SimpleTest;
public class AEADTest extends SimpleTest
{
// EAX test vector from EAXTest
private byte[] K2 = Hex.decode("91945D3F4DCBEE0BF45EF52255F095A4");
private byte[] N2 = Hex.decode("BECAF043B0A23D843194BA972C66DEBD");
private byte[] A2 = Hex.decode("FA3BFD4806EB53FA");
private byte[] P2 = Hex.decode("F7FB");
private byte[] C2 = Hex.decode("19DD5C4C9331049D0BDAB0277408F67967E5");
// C2 with only 64bit MAC (default for EAX)
private byte[] C2_short = Hex.decode("19DD5C4C9331049D0BDA");
private byte[] KGCM = Hex.decode("00000000000000000000000000000000");
private byte[] NGCM = Hex.decode("000000000000000000000000");
private byte[] CGCM = Hex.decode("58e2fccefa7e3061367f1d57a4e7455a");
public String getName()
{
return "AEAD";
}
public void performTest() throws Exception
{
try
{
this.getClass().getClassLoader().loadClass("javax.crypto.spec.GCMParameterSpec");
checkCipherWithAD(K2, N2, A2, P2, C2_short);
testGCMParameterSpec(K2, N2, A2, P2, C2);
testGCMParameterSpecWithRepeatKey(K2, N2, A2, P2, C2);
testGCMGeneric(KGCM, NGCM, new byte[0], new byte[0], CGCM);
}
catch (ClassNotFoundException e)
{
System.err.println("AEADTest disabled due to JDK");
}
}
private void checkCipherWithAD(byte[] K,
byte[] N,
byte[] A,
byte[] P,
byte[] C) throws InvalidKeyException,
NoSuchAlgorithmException, NoSuchPaddingException,
IllegalBlockSizeException, BadPaddingException,
InvalidAlgorithmParameterException, NoSuchProviderException
{
Cipher eax = Cipher.getInstance("AES/EAX/NoPadding", "BC");
SecretKeySpec key = new SecretKeySpec(K, "AES");
IvParameterSpec iv = new IvParameterSpec(N);
eax.init(Cipher.ENCRYPT_MODE, key, iv);
eax.updateAAD(A);
byte[] c = eax.doFinal(P);
if (!areEqual(C, c))
{
fail("JCE encrypt with additional data failed.");
}
eax.init(Cipher.DECRYPT_MODE, key, iv);
eax.updateAAD(A);
byte[] p = eax.doFinal(C);
if (!areEqual(P, p))
{
fail("JCE decrypt with additional data failed.");
}
}
private void testGCMParameterSpec(byte[] K,
byte[] N,
byte[] A,
byte[] P,
byte[] C)
throws InvalidKeyException,
NoSuchAlgorithmException, NoSuchPaddingException,
IllegalBlockSizeException, BadPaddingException,
InvalidAlgorithmParameterException, NoSuchProviderException, IOException
{
Cipher eax = Cipher.getInstance("AES/EAX/NoPadding", "BC");
SecretKeySpec key = new SecretKeySpec(K, "AES");
// GCMParameterSpec mapped to AEADParameters and overrides default MAC
// size
GCMParameterSpec spec = new GCMParameterSpec(128, N);
eax.init(Cipher.ENCRYPT_MODE, key, spec);
eax.updateAAD(A);
byte[] c = eax.doFinal(P);
if (!areEqual(C, c))
{
fail("JCE encrypt with additional data and GCMParameterSpec failed.");
}
eax.init(Cipher.DECRYPT_MODE, key, spec);
eax.updateAAD(A);
byte[] p = eax.doFinal(C);
if (!areEqual(P, p))
{
fail("JCE decrypt with additional data and GCMParameterSpec failed.");
}
AlgorithmParameters algParams = eax.getParameters();
byte[] encParams = algParams.getEncoded();
GCMParameters gcmParameters = GCMParameters.getInstance(encParams);
if (!Arrays.areEqual(spec.getIV(), gcmParameters.getNonce()) || spec.getTLen() != gcmParameters.getIcvLen())
{
fail("parameters mismatch");
}
}
private void testGCMParameterSpecWithRepeatKey(byte[] K,
byte[] N,
byte[] A,
byte[] P,
byte[] C)
throws InvalidKeyException, NoSuchAlgorithmException,
NoSuchPaddingException, IllegalBlockSizeException,
BadPaddingException, InvalidAlgorithmParameterException, NoSuchProviderException, IOException
{
Cipher eax = Cipher.getInstance("AES/EAX/NoPadding", "BC");
SecretKeySpec key = new SecretKeySpec(K, "AES");
GCMParameterSpec spec = new GCMParameterSpec(128, N);
eax.init(Cipher.ENCRYPT_MODE, key, spec);
eax.updateAAD(A);
byte[] c = eax.doFinal(P);
if (!areEqual(C, c))
{
fail("JCE encrypt with additional data and RepeatedSecretKeySpec failed.");
}
// Check GCMParameterSpec handling knows about RepeatedSecretKeySpec
eax.init(Cipher.DECRYPT_MODE, new RepeatedSecretKeySpec("AES"), spec);
eax.updateAAD(A);
byte[] p = eax.doFinal(C);
if (!areEqual(P, p))
{
fail("JCE decrypt with additional data and RepeatedSecretKeySpec failed.");
}
AlgorithmParameters algParams = eax.getParameters();
byte[] encParams = algParams.getEncoded();
GCMParameters gcmParameters = GCMParameters.getInstance(encParams);
if (!Arrays.areEqual(spec.getIV(), gcmParameters.getNonce()) || spec.getTLen() != gcmParameters.getIcvLen())
{
fail("parameters mismatch");
}
}
private void testGCMGeneric(byte[] K,
byte[] N,
byte[] A,
byte[] P,
byte[] C)
throws InvalidKeyException,
NoSuchAlgorithmException, NoSuchPaddingException,
IllegalBlockSizeException, BadPaddingException,
InvalidAlgorithmParameterException, NoSuchProviderException, IOException
{
Cipher eax = Cipher.getInstance("AES/GCM/NoPadding", "BC");
SecretKeySpec key = new SecretKeySpec(K, "AES");
// GCMParameterSpec mapped to AEADParameters and overrides default MAC
// size
GCMParameterSpec spec = new GCMParameterSpec(128, N);
eax.init(Cipher.ENCRYPT_MODE, key, spec);
eax.updateAAD(A);
byte[] c = eax.doFinal(P);
if (!areEqual(C, c))
{
fail("JCE encrypt with additional data and GCMParameterSpec failed.");
}
eax = Cipher.getInstance("GCM", "BC");
eax.init(Cipher.DECRYPT_MODE, key, spec);
eax.updateAAD(A);
byte[] p = eax.doFinal(C);
if (!areEqual(P, p))
{
fail("JCE decrypt with additional data and GCMParameterSpec failed.");
}
AlgorithmParameters algParams = eax.getParameters();
byte[] encParams = algParams.getEncoded();
GCMParameters gcmParameters = GCMParameters.getInstance(encParams);
if (!Arrays.areEqual(spec.getIV(), gcmParameters.getNonce()) || spec.getTLen() != gcmParameters.getIcvLen())
{
fail("parameters mismatch");
}
}
public static void main(String[] args) throws Exception
{
Security.addProvider(new BouncyCastleProvider());
runTest(new AEADTest());
}
}