JCE: fix Cipher.getOutputSize() for AES/GCM/NoPadding in DECRYPT mode, should remove tag from length
parent
ab70102343
commit
dbfbe28cab
|
@ -303,12 +303,19 @@ public class WolfCryptCipher extends CipherSpi {
|
|||
if (paddingType == PaddingType.WC_NONE) {
|
||||
if (cipherMode == CipherMode.WC_GCM) {
|
||||
/* In AES-GCM mode we append the authentication tag
|
||||
* to the end of ciphertext */
|
||||
size = inputLen + this.gcmTagLen;
|
||||
* to the end of ciphertext, When decrypting, output
|
||||
* size will have it taken off. */
|
||||
if (this.direction == OpMode.WC_ENCRYPT) {
|
||||
size = inputLen + this.gcmTagLen;
|
||||
}
|
||||
else {
|
||||
size = inputLen - this.gcmTagLen;
|
||||
}
|
||||
size = Math.max(size, 0);
|
||||
}
|
||||
else {
|
||||
/* wolfCrypt expects input to be padded by application to
|
||||
* block size, thus output is same size as input */
|
||||
/* wolfCrypt expects input to be padded by application
|
||||
* to block size, thus output is same size as input */
|
||||
size = inputLen;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2250,6 +2250,66 @@ public class WolfCryptCipherTest {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test Cipher("AES/GCM/NoPadding") getOutputSize() method for various
|
||||
* use cases.
|
||||
*/
|
||||
@Test
|
||||
public void testAesGcmGetOutputSize() throws Exception {
|
||||
|
||||
final int TAG_LENGTH_BYTES = 16; /* Default tag length */
|
||||
final int KEY_LENGTH_BYTES = 16; /* 128-bit AES key */
|
||||
final int IV_LENGTH_BYTES = 12;
|
||||
|
||||
/* Fill key and IV with non-zero values */
|
||||
byte[] keyBytes = new byte[KEY_LENGTH_BYTES];
|
||||
java.util.Arrays.fill(keyBytes, (byte) 0x01);
|
||||
SecretKeySpec key = new SecretKeySpec(keyBytes, "AES");
|
||||
|
||||
byte[] iv = new byte[IV_LENGTH_BYTES];
|
||||
java.util.Arrays.fill(iv, (byte) 0x02);
|
||||
GCMParameterSpec spec = new GCMParameterSpec(TAG_LENGTH_BYTES * 8, iv);
|
||||
|
||||
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", jceProvider);
|
||||
|
||||
/* Test ENCRYPT with zero-length input */
|
||||
cipher.init(Cipher.ENCRYPT_MODE, key, spec);
|
||||
assertEquals("Output size for zero-length input should be tag length",
|
||||
TAG_LENGTH_BYTES, cipher.getOutputSize(0));
|
||||
|
||||
/* Test ENCRYPT with small input, re-init to reset state */
|
||||
cipher.init(Cipher.ENCRYPT_MODE, key, spec);
|
||||
assertEquals("Output size should be input length plus tag length",
|
||||
10 + TAG_LENGTH_BYTES, cipher.getOutputSize(10));
|
||||
|
||||
/* Test ENCRYPT with block boundary input */
|
||||
cipher.init(Cipher.ENCRYPT_MODE, key, spec);
|
||||
assertEquals("Output size should be input length plus tag length " +
|
||||
"at block boundary", 16 + TAG_LENGTH_BYTES,
|
||||
cipher.getOutputSize(16));
|
||||
|
||||
/* Test DECRYPT with tag included */
|
||||
cipher.init(Cipher.DECRYPT_MODE, key, spec);
|
||||
assertEquals("Output size for decryption should be input length " +
|
||||
"minus tag length", 10, cipher.getOutputSize(10 + TAG_LENGTH_BYTES));
|
||||
|
||||
/* Test ENCRYPT after partial update */
|
||||
byte[] partialInput = new byte[5];
|
||||
cipher.init(Cipher.ENCRYPT_MODE, key, spec);
|
||||
cipher.update(partialInput); /* Process some data */
|
||||
assertEquals("Output size after update should account for remaining " +
|
||||
"input plus tag", 10 + TAG_LENGTH_BYTES, cipher.getOutputSize(10));
|
||||
|
||||
/* Test getOutputSize() before initialization, expect exception */
|
||||
Cipher uninitializedCipher = Cipher.getInstance("AES/GCM/NoPadding");
|
||||
try {
|
||||
uninitializedCipher.getOutputSize(10);
|
||||
fail("Expected IllegalStateException for uninitialized cipher");
|
||||
} catch (IllegalStateException e) {
|
||||
/* Expected exception */
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDESedeCbcNoPadding()
|
||||
throws NoSuchProviderException, NoSuchAlgorithmException,
|
||||
|
|
Loading…
Reference in New Issue