Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix implementation of engineGetOutputSize(), add tests #62

Merged
merged 2 commits into from
Jan 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/main/java/com/canonical/openssl/cipher/CipherAes.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,15 @@ protected int engineGetBlockSize() {

@Override
protected int engineGetOutputSize(int inputSize) {
if(getPadding().equals("NONE"))
return inputSize;

int blockSize = engineGetBlockSize();
if(getMode().equals("CBC") || getMode().equals("ECB")) {
int paddingLength = (blockSize - (inputSize % blockSize)) % blockSize;
return inputSize + paddingLength;
}

return inputSize;
}
}
129 changes: 124 additions & 5 deletions src/test/java/CipherTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import org.junit.BeforeClass;
import static org.junit.Assert.fail;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;

public class CipherTest {

Expand Down Expand Up @@ -156,6 +157,7 @@ private void runTestMultipleUpdates(String nameKeySizeAndMode, String padding) t
private void runTestSingleUpdate(String nameKeySizeAndMode, String padding) throws Exception {
SecureRandom sr = SecureRandom.getInstance("NativePRNG");
String cipherName = nameKeySizeAndMode + "/" + padding;
Cipher cipher = Cipher.getInstance(cipherName, "OpenSSLFIPSProvider");

byte[] key;
String keySize = nameKeySizeAndMode.split("/")[0].substring(3);
Expand All @@ -174,10 +176,8 @@ private void runTestSingleUpdate(String nameKeySizeAndMode, String padding) thro

byte[] iv = new byte[16];
sr.nextBytes(iv);

AlgorithmParameterSpec spec = new IvParameterSpec(iv);

Cipher cipher = Cipher.getInstance(cipherName, "OpenSSLFIPSProvider");
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"), spec, sr);

byte[] input = new byte[16];
Expand All @@ -191,8 +191,127 @@ private void runTestSingleUpdate(String nameKeySizeAndMode, String padding) thro

assertArrayEquals("Single update cipher test for " + cipherName + " failed", input, output);
}

}


private void runTestGetOutputSize(String nameKeySizeAndMode, String padding) throws Exception {
String cipherName = nameKeySizeAndMode + "/" + padding;
SecureRandom sr = SecureRandom.getInstance("NativePRNG");

byte[] key;
String keySize = nameKeySizeAndMode.split("/")[0].substring(3);
if (keySize.equals("128")) {
key = new byte[16];
} else if (keySize.equals("192")) {
key = new byte[24];
} else if (keySize.equals("256")) {
key = new byte[32];
} else {
fail("Key size unsupported");
return;
}

sr.nextBytes(key);

byte[] iv = new byte[16];
sr.nextBytes(iv);
AlgorithmParameterSpec spec = new IvParameterSpec(iv);

Cipher cipher = Cipher.getInstance(nameKeySizeAndMode + "/" + padding, "OpenSSLFIPSProvider");
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"), spec, sr);

int inputSize = 512;
if (!padding.equals("NONE")) {
inputSize = 511;
}
byte[] input = new byte[inputSize];
sr.nextBytes(input);

byte[] fullInput = new byte[inputSize*2];
System.arraycopy(input, 0, fullInput, 0, inputSize);
System.arraycopy(input, 0, fullInput, inputSize, inputSize);

byte[] fullEnc = new byte[cipher.getOutputSize(inputSize*2)];
int encLen = 0;

byte[] enc1 = cipher.update(input, 0, input.length);
System.arraycopy(enc1, 0, fullEnc, 0, enc1.length);
encLen += enc1.length;

byte[] enc2 = cipher.doFinal(input, 0, input.length);
System.arraycopy(enc2, 0, fullEnc, encLen, enc2.length);
encLen += enc2.length;

assertEquals("Encrypted text has an unexpected length for " + cipherName, encLen, cipher.getOutputSize(inputSize*2));

Cipher decipher = Cipher.getInstance(nameKeySizeAndMode + "/" + padding, "OpenSSLFIPSProvider");
decipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "AES"), spec, sr);
byte[] output = decipher.doFinal(fullEnc, 0, fullEnc.length);
assertArrayEquals("Multi-update cipher test for " + cipherName + " failed", fullInput, output);
}

@Test
public void testBlockSize() throws Exception {
for (String cipher : ciphers) {
for(String padding : paddings) {
runTestBlockSize(cipher, padding);
}
}
}

@Test
public void testGetOutputSize() throws Exception {
for (String cipher : ciphers) {
if (cipher.endsWith("CCM"))
continue;

for(String padding : paddings) {
runTestGetOutputSize(cipher, padding);
}
}
}

@Test
public void testGetIV() throws Exception {
for (String cipher : ciphers) {
for(String padding : paddings) {
runTestGetIV(cipher, padding);
}
}
}

private void runTestBlockSize(String cipherName, String padding) throws Exception {
String fullName = cipherName + "/" + padding;
Cipher cipher = Cipher.getInstance(fullName, "OpenSSLFIPSProvider");
assertEquals("Invalid block size", cipher.getBlockSize(), 16);
}

private void runTestGetIV(String nameKeySizeAndMode, String padding) throws Exception {
SecureRandom sr = SecureRandom.getInstance("NativePRNG");
String cipherName = nameKeySizeAndMode + "/" + padding;

Cipher cipher = Cipher.getInstance(cipherName, "OpenSSLFIPSProvider");

byte[] key;
String keySize = nameKeySizeAndMode.split("/")[0].substring(3);
if (keySize.equals("128")) {
key = new byte[16];
} else if (keySize.equals("192")) {
key = new byte[24];
} else if (keySize.equals("256")) {
key = new byte[32];
} else {
fail("Key size unsupported");
return;
}

sr.nextBytes(key);

byte[] iv = new byte[16];
sr.nextBytes(iv);

AlgorithmParameterSpec spec = new IvParameterSpec(iv);

cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"), spec, sr);
byte[] retIV = cipher.getIV();
assertArrayEquals("Returned IV does not match supplied IV", iv, retIV);
}
}
Loading