Skip to content

Commit b13f649

Browse files
authored
Merge pull request #142 from cconlon/CipherGenericAes
Add `Cipher.getInstance("AES")` support
2 parents 8bdce7c + b81af66 commit b13f649

File tree

3 files changed

+74
-5
lines changed

3 files changed

+74
-5
lines changed

README_JCE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ The JCE provider currently supports the following algorithms:
107107
AES/CCM/NoPadding
108108
AES/CTR/NoPadding
109109
AES/ECB/NoPadding
110-
AES/ECB/PKCS5Padding
110+
AES/ECB/PKCS5Padding (aliased also as: AES)
111111
AES/GCM/NoPadding
112112
AES/OFB/NoPadding
113113
DESede/CBC/NoPadding

src/main/java/com/wolfssl/provider/jce/WolfCryptProvider.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,13 @@ private void registerServices() {
281281
"com.wolfssl.provider.jce.WolfCryptCipher$wcAESECBNoPadding");
282282
put("Cipher.AES/ECB/PKCS5Padding",
283283
"com.wolfssl.provider.jce.WolfCryptCipher$wcAESECBPKCS5Padding");
284+
285+
/* SunJCE and Bouncy Castle alias AES to AES/ECB/PKCS5Padding,
286+
* we do the same here for compatibility. */
287+
put("Cipher.AES",
288+
"com.wolfssl.provider.jce.WolfCryptCipher$wcAESECBPKCS5Padding");
289+
put("Cipher.AES SupportedModes", "ECB");
290+
put("Cipher.AES SupportedPaddings", "NoPadding, PKCS5Padding");
284291
}
285292
if (FeatureDetect.AesCtrEnabled()) {
286293
put("Cipher.AES/CTR/NoPadding",

src/test/java/com/wolfssl/provider/jce/test/WolfCryptCipherTest.java

Lines changed: 66 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ public class WolfCryptCipherTest {
7878
"AES/CCM/NoPadding",
7979
"AES/CTR/NoPadding",
8080
"AES/ECB/NoPadding",
81+
"AES", /* maps to AES/ECB/PKCS5Padding */
8182
"AES/ECB/PKCS5Padding",
8283
"AES/GCM/NoPadding",
8384
"AES/OFB/NoPadding",
@@ -138,6 +139,7 @@ public static void testProviderInstallationAtRuntime()
138139
expectedBlockSizes.put("AES/CCM/NoPadding", 16);
139140
expectedBlockSizes.put("AES/CTR/NoPadding", 16);
140141
expectedBlockSizes.put("AES/ECB/NoPadding", 16);
142+
expectedBlockSizes.put("AES", 16);
141143
expectedBlockSizes.put("AES/ECB/PKCS5Padding", 16);
142144
expectedBlockSizes.put("AES/GCM/NoPadding", 16);
143145
expectedBlockSizes.put("AES/OFB/NoPadding", 16);
@@ -761,6 +763,63 @@ public void testAesCbcNoPaddingBigMessage()
761763
assertArrayEquals(plain, input);
762764
}
763765

766+
/* Cipher.getInstance("AES") is just AES/ECB/PKCS5Padding, so we
767+
* do one test that here. */
768+
@Test
769+
public void testAesGeneric()
770+
throws NoSuchProviderException, NoSuchAlgorithmException,
771+
NoSuchPaddingException, InvalidKeyException,
772+
IllegalBlockSizeException, InvalidAlgorithmParameterException,
773+
BadPaddingException {
774+
775+
if (!FeatureDetect.AesEcbEnabled()) {
776+
/* skip if AES is not enabled */
777+
return;
778+
}
779+
780+
byte key[] = new byte[] {
781+
(byte)0x2b, (byte)0x7e, (byte)0x15, (byte)0x16,
782+
(byte)0x28, (byte)0xae, (byte)0xd2, (byte)0xa6,
783+
(byte)0xab, (byte)0xf7, (byte)0x15, (byte)0x88,
784+
(byte)0x09, (byte)0xcf, (byte)0x4f, (byte)0x3c
785+
};
786+
787+
/* Test with data that needs padding.
788+
* 12 bytes, needs 4 bytes padding */
789+
byte input[] = "Hello World!".getBytes();
790+
791+
Cipher cipher = Cipher.getInstance("AES", jceProvider);
792+
SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
793+
794+
/* Test encryption */
795+
cipher.init(Cipher.ENCRYPT_MODE, keySpec);
796+
byte[] ciphertext = cipher.doFinal(input);
797+
798+
/* Ciphertext should be block-aligned (16 bytes) */
799+
assertEquals(16, ciphertext.length);
800+
801+
/* Test decryption */
802+
cipher.init(Cipher.DECRYPT_MODE, keySpec);
803+
byte[] decrypted = cipher.doFinal(ciphertext);
804+
805+
assertArrayEquals(input, decrypted);
806+
807+
/* Test with exact block size data */
808+
byte blockSizeInput[] = new byte[16];
809+
Arrays.fill(blockSizeInput, (byte)0x41); /* Fill with 'A' */
810+
811+
cipher.init(Cipher.ENCRYPT_MODE, keySpec);
812+
byte[] blockCiphertext = cipher.doFinal(blockSizeInput);
813+
814+
/* Should be 32 bytes (original 16 + 16 bytes padding) */
815+
assertEquals(32, blockCiphertext.length);
816+
817+
cipher.init(Cipher.DECRYPT_MODE, keySpec);
818+
byte[] blockDecrypted = cipher.doFinal(blockCiphertext);
819+
820+
assertArrayEquals(blockSizeInput, blockDecrypted);
821+
}
822+
764823
@Test
765824
public void testAesCbcPKCS5Padding()
766825
throws NoSuchProviderException, NoSuchAlgorithmException,
@@ -4339,7 +4398,8 @@ public void testIVConsistencyAcrossOperations() throws Exception {
43394398
/* Test all enabled cipher modes that use IVs (exclude RSA and ECB) */
43404399
for (String mode : enabledJCEAlgos) {
43414400
/* Skip modes that don't use IVs */
4342-
if (mode.startsWith("RSA") || mode.contains("/ECB/")) {
4401+
if (mode.startsWith("RSA") || mode.contains("/ECB/") ||
4402+
mode.equals("AES")) {
43434403
continue;
43444404
}
43454405

@@ -4368,14 +4428,15 @@ private void testIVConsistencyForMode(String algorithm) throws Exception {
43684428
/* Generate test key */
43694429
if (algorithm.startsWith("AES")) {
43704430
key = new byte[16]; /* AES-128 */
4431+
keySpec = new SecretKeySpec(key, "AES");
43714432
} else if (algorithm.startsWith("DESede")) {
43724433
key = new byte[24]; /* 3DES */
4434+
keySpec = new SecretKeySpec(key, "DESede");
43734435
} else {
43744436
return; /* Unsupported algorithm */
43754437
}
43764438

43774439
secureRandom.nextBytes(key);
4378-
keySpec = new SecretKeySpec(key, algorithm.split("/")[0]);
43794440

43804441
/* Generate test data of various sizes to ensure robustness */
43814442
for (int dataSize : testSizes) {
@@ -4399,8 +4460,9 @@ private void testIVConsistencyForModeAndSize(String algorithm,
43994460
byte[] ivAfterDecryption;
44004461

44014462
/* Skip sizes that would cause issues with block ciphers */
4402-
if ((algorithm.contains("CBC") || algorithm.contains("ECB")) &&
4403-
algorithm.contains("NoPadding") && (dataSize % 16 != 0)) {
4463+
if ((algorithm.equals("AES") ||
4464+
((algorithm.contains("CBC") || algorithm.contains("ECB")) &&
4465+
algorithm.contains("NoPadding"))) && (dataSize % 16 != 0)) {
44044466
return; /* Block size must be multiple of 16 for NoPadding */
44054467
}
44064468
if (algorithm.startsWith("DESede") &&

0 commit comments

Comments
 (0)