Merge pull request #51 from cconlon/aesPkcs5Padding
JCE: add support for Cipher AES/CBC/PKCS5Padding, RSApull/52/head
commit
fbfa297cc4
|
@ -38,7 +38,9 @@ The JCE provider currently supports the following algorithms:
|
|||
|
||||
Cipher Class
|
||||
AES/CBC/NoPadding
|
||||
AES/CBC/PKCS5Padding
|
||||
DESede/CBC/NoPadding
|
||||
RSA
|
||||
RSA/ECB/PKCS1Padding
|
||||
|
||||
Mac Class
|
||||
|
|
|
@ -36,20 +36,24 @@
|
|||
JNIEXPORT jlong JNICALL Java_com_wolfssl_wolfcrypt_Aes_mallocNativeStruct(
|
||||
JNIEnv* env, jobject this)
|
||||
{
|
||||
jlong ret = 0;
|
||||
void* ret = NULL;
|
||||
|
||||
#ifndef NO_AES
|
||||
ret = (jlong) XMALLOC(sizeof(Aes), NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
ret = (void*)XMALLOC(sizeof(Aes), NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
|
||||
if (!ret)
|
||||
if (ret == NULL) {
|
||||
throwOutOfMemoryException(env, "Failed to allocate Aes object");
|
||||
}
|
||||
else {
|
||||
XMEMSET(ret, 0, sizeof(Aes));
|
||||
}
|
||||
|
||||
LogStr("new Aes() = %p\n", (void*)ret);
|
||||
LogStr("new Aes() = %p\n", ret);
|
||||
#else
|
||||
throwNotCompiledInException(env);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
return (jlong)ret;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
|
|
|
@ -868,7 +868,7 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Fips_Des3_1SetKey_1fips__Lcom_
|
|||
jint ret = NOT_COMPILED_IN;
|
||||
|
||||
#if defined(HAVE_FIPS) && \
|
||||
(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) && \
|
||||
(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION <= 2)) && \
|
||||
!defined(NO_DES3)
|
||||
|
||||
Des3* des = NULL;
|
||||
|
@ -908,7 +908,7 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Fips_Des3_1SetKey_1fips__Lcom_
|
|||
jint ret = NOT_COMPILED_IN;
|
||||
|
||||
#if defined(HAVE_FIPS) && \
|
||||
(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) && \
|
||||
(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION <= 2)) && \
|
||||
!defined(NO_DES3)
|
||||
|
||||
Des3* des = NULL;
|
||||
|
@ -948,7 +948,7 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Fips_Des3_1SetIV_1fips__Lcom_w
|
|||
jint ret = NOT_COMPILED_IN;
|
||||
|
||||
#if defined(HAVE_FIPS) && \
|
||||
(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) && \
|
||||
(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION <= 2)) && \
|
||||
!defined(NO_DES3)
|
||||
|
||||
Des3* des = NULL;
|
||||
|
@ -981,7 +981,7 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Fips_Des3_1SetIV_1fips__Lcom_w
|
|||
jint ret = NOT_COMPILED_IN;
|
||||
|
||||
#if defined(HAVE_FIPS) && \
|
||||
(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) && \
|
||||
(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION <= 2)) && \
|
||||
!defined(NO_DES3)
|
||||
|
||||
Des3* des = NULL;
|
||||
|
@ -1016,7 +1016,7 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Fips_Des3_1CbcEncrypt_1fips__L
|
|||
jint ret = NOT_COMPILED_IN;
|
||||
|
||||
#if defined(HAVE_FIPS) && \
|
||||
(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) && \
|
||||
(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION <= 2)) && \
|
||||
!defined(NO_DES3)
|
||||
|
||||
Des3* des = NULL;
|
||||
|
@ -1055,7 +1055,7 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Fips_Des3_1CbcEncrypt_1fips__L
|
|||
jint ret = NOT_COMPILED_IN;
|
||||
|
||||
#if defined(HAVE_FIPS) && \
|
||||
(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) && \
|
||||
(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION <= 2)) && \
|
||||
!defined(NO_DES3)
|
||||
|
||||
Des3* des = NULL;
|
||||
|
@ -1096,7 +1096,7 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Fips_Des3_1CbcDecrypt_1fips__L
|
|||
jint ret = NOT_COMPILED_IN;
|
||||
|
||||
#if defined(HAVE_FIPS) && \
|
||||
(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) && \
|
||||
(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION <= 2)) && \
|
||||
!defined(NO_DES3)
|
||||
|
||||
Des3* des = NULL;
|
||||
|
@ -1135,7 +1135,7 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Fips_Des3_1CbcDecrypt_1fips__L
|
|||
jint ret = NOT_COMPILED_IN;
|
||||
|
||||
#if defined(HAVE_FIPS) && \
|
||||
(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) && \
|
||||
(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION <= 2)) && \
|
||||
!defined(NO_DES3)
|
||||
|
||||
Des3* des = NULL;
|
||||
|
|
|
@ -70,7 +70,8 @@ public class WolfCryptCipher extends CipherSpi {
|
|||
|
||||
enum PaddingType {
|
||||
WC_NONE,
|
||||
WC_PKCS1
|
||||
WC_PKCS1,
|
||||
WC_PKCS5
|
||||
}
|
||||
|
||||
enum OpMode {
|
||||
|
@ -204,6 +205,16 @@ public class WolfCryptCipher extends CipherSpi {
|
|||
if (debug.DEBUG)
|
||||
log("set padding to PKCS1Padding");
|
||||
}
|
||||
|
||||
} else if (padding.equals("PKCS5Padding")) {
|
||||
|
||||
if (cipherType == CipherType.WC_AES) {
|
||||
paddingType = PaddingType.WC_PKCS5;
|
||||
supported = 1;
|
||||
|
||||
if (debug.DEBUG)
|
||||
log("set padding to PKCS5Padding");
|
||||
}
|
||||
}
|
||||
|
||||
if (supported == 0) {
|
||||
|
@ -218,16 +229,44 @@ public class WolfCryptCipher extends CipherSpi {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected int engineGetOutputSize(int inputLen) {
|
||||
protected int engineGetOutputSize(int inputLen)
|
||||
throws IllegalStateException {
|
||||
|
||||
int size = 0;
|
||||
|
||||
switch (this.cipherType) {
|
||||
case WC_AES:
|
||||
if (paddingType == PaddingType.WC_NONE) {
|
||||
/* wolfCrypt expects input to be padded by application to
|
||||
* block size, thus output is same size as input */
|
||||
size = inputLen;
|
||||
}
|
||||
else if (paddingType == PaddingType.WC_PKCS5) {
|
||||
size = buffered.length + inputLen;
|
||||
size += Aes.getPKCS7PadSize(size, Aes.BLOCK_SIZE);
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException(
|
||||
"Unsupported padding mode for Cipher Aes");
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case WC_DES3:
|
||||
/* wolfCrypt expects input to be padded by application to
|
||||
* block size, thus output is same size as input */
|
||||
size = inputLen;
|
||||
if (paddingType == PaddingType.WC_NONE) {
|
||||
/* wolfCrypt expects input to be padded by application to
|
||||
* block size, thus output is same size as input */
|
||||
size = inputLen;
|
||||
}
|
||||
else if (paddingType == PaddingType.WC_PKCS5) {
|
||||
size = buffered.length + inputLen;
|
||||
size += Des3.getPKCS7PadSize(size, Des3.BLOCK_SIZE);
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException(
|
||||
"Unsupported padding mode for Cipher Des3");
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case WC_RSA:
|
||||
|
@ -474,8 +513,10 @@ public class WolfCryptCipher extends CipherSpi {
|
|||
|
||||
int blocks = 0;
|
||||
int remaining = 0;
|
||||
byte tmpOut[] = null;
|
||||
byte tmpIn[] = null;
|
||||
int bytesToProcess = 0;
|
||||
byte[] output = null;
|
||||
byte[] tmpIn = null;
|
||||
byte[] tmpBuf = null;
|
||||
|
||||
if (input == null || len < 0)
|
||||
throw new IllegalArgumentException("Null input buffer or len < 0");
|
||||
|
@ -485,48 +526,61 @@ public class WolfCryptCipher extends CipherSpi {
|
|||
return null;
|
||||
}
|
||||
|
||||
if ((cipherType == CipherType.WC_RSA) ||
|
||||
((buffered.length + len) < blockSize)) {
|
||||
/* buffer for short inputs, or RSA */
|
||||
if (len > 0) {
|
||||
/* add input bytes to buffered */
|
||||
tmpIn = new byte[buffered.length + len];
|
||||
System.arraycopy(buffered, 0, tmpIn, 0, buffered.length);
|
||||
System.arraycopy(input, inputOffset, tmpIn, buffered.length, len);
|
||||
buffered = tmpIn;
|
||||
return null;
|
||||
}
|
||||
|
||||
/* do update on block size multiples only */
|
||||
blocks = (buffered.length + len) / blockSize;
|
||||
remaining = (buffered.length + len) % blockSize;
|
||||
/* keep buffered data if RSA or data is less than block size */
|
||||
if (cipherType == CipherType.WC_RSA ||
|
||||
buffered.length < blockSize) {
|
||||
return new byte[0];
|
||||
}
|
||||
|
||||
tmpIn = new byte[blocks * blockSize];
|
||||
System.arraycopy(buffered, 0, tmpIn, 0, buffered.length);
|
||||
System.arraycopy(input, inputOffset, tmpIn, buffered.length,
|
||||
len - remaining);
|
||||
/* calculate blocks and partial non-block size remaining */
|
||||
blocks = buffered.length / blockSize;
|
||||
remaining = buffered.length % blockSize;
|
||||
bytesToProcess = blocks * blockSize;
|
||||
|
||||
/* if PKCS#5/7 padding, and decrypting, hold on to last block for
|
||||
* padding check in wolfCryptFinal() */
|
||||
if (paddingType == PaddingType.WC_PKCS5 &&
|
||||
direction == OpMode.WC_DECRYPT) {
|
||||
bytesToProcess -= blockSize;
|
||||
}
|
||||
|
||||
/* not enough data to process yet return until more or final */
|
||||
if (bytesToProcess == 0) {
|
||||
return new byte[0];
|
||||
}
|
||||
|
||||
tmpIn = new byte[bytesToProcess];
|
||||
System.arraycopy(buffered, 0, tmpIn, 0, bytesToProcess);
|
||||
|
||||
/* buffer remaining non-block size input, or reset */
|
||||
buffered = new byte[remaining];
|
||||
if (remaining > 0) {
|
||||
System.arraycopy(input, inputOffset + (len - remaining),
|
||||
buffered, 0, remaining);
|
||||
}
|
||||
tmpBuf = new byte[buffered.length - bytesToProcess];
|
||||
System.arraycopy(buffered, bytesToProcess, tmpBuf, 0, tmpBuf.length);
|
||||
buffered = tmpBuf;
|
||||
|
||||
/* process tmp[] */
|
||||
/* process tmpIn[] */
|
||||
switch (this.cipherType) {
|
||||
|
||||
case WC_AES:
|
||||
tmpOut = this.aes.update(tmpIn, 0, tmpIn.length);
|
||||
output = this.aes.update(tmpIn, 0, tmpIn.length);
|
||||
|
||||
/* truncate */
|
||||
tmpOut = Arrays.copyOfRange(tmpOut, 0, tmpIn.length);
|
||||
output = Arrays.copyOfRange(output, 0, tmpIn.length);
|
||||
|
||||
break;
|
||||
|
||||
case WC_DES3:
|
||||
tmpOut = this.des3.update(tmpIn, 0, tmpIn.length);
|
||||
output = this.des3.update(tmpIn, 0, tmpIn.length);
|
||||
|
||||
/* truncate */
|
||||
tmpOut = Arrays.copyOfRange(tmpOut, 0, tmpIn.length);
|
||||
output = Arrays.copyOfRange(output, 0, tmpIn.length);
|
||||
|
||||
break;
|
||||
|
||||
|
@ -534,7 +588,12 @@ public class WolfCryptCipher extends CipherSpi {
|
|||
throw new RuntimeException("Unsupported algorithm type");
|
||||
};
|
||||
|
||||
return tmpOut;
|
||||
if (output == null) {
|
||||
/* For interop compatibility, return empty byte array */
|
||||
output = new byte[0];
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
private byte[] wolfCryptFinal(byte[] input, int inputOffset, int len)
|
||||
|
@ -546,7 +605,11 @@ public class WolfCryptCipher extends CipherSpi {
|
|||
|
||||
totalSz = buffered.length + len;
|
||||
|
||||
if (isBlockCipher() && (totalSz % blockSize != 0)) {
|
||||
if (isBlockCipher() &&
|
||||
(this.direction == OpMode.WC_DECRYPT ||
|
||||
(this.direction == OpMode.WC_ENCRYPT &&
|
||||
this.paddingType != PaddingType.WC_PKCS5)) &&
|
||||
(totalSz % blockSize != 0)) {
|
||||
throw new IllegalBlockSizeException(
|
||||
"Input length not multiple of " + blockSize + " bytes");
|
||||
}
|
||||
|
@ -554,8 +617,21 @@ public class WolfCryptCipher extends CipherSpi {
|
|||
/* do final encrypt over totalSz */
|
||||
tmpIn = new byte[totalSz];
|
||||
System.arraycopy(buffered, 0, tmpIn, 0, buffered.length);
|
||||
if (input != null && len > 0)
|
||||
if (input != null && len > 0) {
|
||||
System.arraycopy(input, inputOffset, tmpIn, buffered.length, len);
|
||||
}
|
||||
|
||||
/* add padding if encrypting and PKCS5 padding is used. PKCS#5 padding
|
||||
* is treated the same as PKCS#7 padding here, using each algorithm's
|
||||
* specific block size */
|
||||
if (this.direction == OpMode.WC_ENCRYPT &&
|
||||
this.paddingType == PaddingType.WC_PKCS5) {
|
||||
if (this.cipherType == CipherType.WC_AES) {
|
||||
tmpIn = Aes.padPKCS7(tmpIn, Aes.BLOCK_SIZE);
|
||||
} else if (this.cipherType == CipherType.WC_DES3) {
|
||||
tmpIn = Des3.padPKCS7(tmpIn, Des3.BLOCK_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
switch (this.cipherType) {
|
||||
|
||||
|
@ -565,6 +641,12 @@ public class WolfCryptCipher extends CipherSpi {
|
|||
/* truncate */
|
||||
tmpOut = Arrays.copyOfRange(tmpOut, 0, tmpIn.length);
|
||||
|
||||
/* strip PKCS#5/PKCS#7 padding if required */
|
||||
if (this.direction == OpMode.WC_DECRYPT &&
|
||||
this.paddingType == PaddingType.WC_PKCS5) {
|
||||
tmpOut = Aes.unPadPKCS7(tmpOut, Aes.BLOCK_SIZE);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case WC_DES3:
|
||||
|
@ -573,6 +655,12 @@ public class WolfCryptCipher extends CipherSpi {
|
|||
/* truncate */
|
||||
tmpOut = Arrays.copyOfRange(tmpOut, 0, tmpIn.length);
|
||||
|
||||
/* strip PKCS#5/PKCS#7 padding if required */
|
||||
if (this.direction == OpMode.WC_DECRYPT &&
|
||||
this.paddingType == PaddingType.WC_PKCS5) {
|
||||
tmpOut = Des3.unPadPKCS7(tmpOut, Des3.BLOCK_SIZE);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case WC_RSA:
|
||||
|
@ -793,6 +881,19 @@ public class WolfCryptCipher extends CipherSpi {
|
|||
super(CipherType.WC_AES, CipherMode.WC_CBC, PaddingType.WC_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class for AES-CBC with PKCS#5 padding
|
||||
*/
|
||||
public static final class wcAESCBCPKCS5Padding extends WolfCryptCipher {
|
||||
/**
|
||||
* Create new wcAESCBCPkcs5Padding object
|
||||
*/
|
||||
public wcAESCBCPKCS5Padding() {
|
||||
super(CipherType.WC_AES, CipherMode.WC_CBC, PaddingType.WC_PKCS5);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class for DES-EDE-CBC with no padding
|
||||
*/
|
||||
|
@ -804,6 +905,7 @@ public class WolfCryptCipher extends CipherSpi {
|
|||
super(CipherType.WC_DES3, CipherMode.WC_CBC, PaddingType.WC_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class for RSA-ECB with PKCS1 padding
|
||||
*/
|
||||
|
|
|
@ -121,10 +121,14 @@ public final class WolfCryptProvider extends Provider {
|
|||
/* Cipher */
|
||||
put("Cipher.AES/CBC/NoPadding",
|
||||
"com.wolfssl.provider.jce.WolfCryptCipher$wcAESCBCNoPadding");
|
||||
put("Cipher.AES/CBC/PKCS5Padding",
|
||||
"com.wolfssl.provider.jce.WolfCryptCipher$wcAESCBCPKCS5Padding");
|
||||
|
||||
put("Cipher.DESede/CBC/NoPadding",
|
||||
"com.wolfssl.provider.jce.WolfCryptCipher$wcDESedeCBCNoPadding");
|
||||
|
||||
put("Cipher.RSA",
|
||||
"com.wolfssl.provider.jce.WolfCryptCipher$wcRSAECBPKCS1Padding");
|
||||
put("Cipher.RSA/ECB/PKCS1Padding",
|
||||
"com.wolfssl.provider.jce.WolfCryptCipher$wcRSAECBPKCS1Padding");
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
package com.wolfssl.wolfcrypt;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import javax.crypto.ShortBufferException;
|
||||
|
@ -192,4 +193,120 @@ public abstract class BlockCipher extends NativeStruct {
|
|||
state = WolfCryptState.UNINITIALIZED;
|
||||
setNativeStruct(NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return number of PKCS#7 pad bytes required given input size.
|
||||
*
|
||||
* @param inputSize size to calculate needed PKCS#7 pad bytes
|
||||
* @param blockSize Block size of algorithm being used
|
||||
*
|
||||
* @return Number of PKCS#7 pad bytes that would be appended to an input
|
||||
* of size inputSize.
|
||||
*/
|
||||
public static int getPKCS7PadSize(int inputSize, int blockSize) {
|
||||
|
||||
int padSz = 0;
|
||||
|
||||
if (inputSize == 0 || blockSize == 0) {
|
||||
throw new WolfCryptException(
|
||||
"Input or block size is 0");
|
||||
}
|
||||
|
||||
padSz = blockSize - (inputSize % blockSize);
|
||||
|
||||
return padSz;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pad input data with PKCS#7 padding.
|
||||
*
|
||||
* @param in Input data to be padded
|
||||
* @param blockSize Block size of algorithm being used
|
||||
*
|
||||
* @return Byte array which includes PKCS#7 padding on end
|
||||
*
|
||||
* @throws WolfCryptException if input is null, zero length,
|
||||
* or blockSize is invalid
|
||||
*/
|
||||
public static byte[] padPKCS7(byte[] in, int blockSize)
|
||||
throws WolfCryptException {
|
||||
|
||||
int padSz = 0;
|
||||
byte[] padded = null;
|
||||
|
||||
if (in == null) {
|
||||
throw new WolfCryptException(
|
||||
"Input array is null");
|
||||
}
|
||||
|
||||
if (blockSize == 0) {
|
||||
throw new WolfCryptException("Block size is 0");
|
||||
}
|
||||
|
||||
padSz = blockSize - (in.length % blockSize);
|
||||
padded = new byte[in.length + padSz];
|
||||
|
||||
System.arraycopy(in, 0, padded, 0, in.length);
|
||||
|
||||
try {
|
||||
Arrays.fill(padded, in.length, padded.length, (byte)(padSz & 0xff));
|
||||
} catch (IllegalArgumentException | ArrayIndexOutOfBoundsException e) {
|
||||
throw new WolfCryptException(e);
|
||||
}
|
||||
|
||||
return padded;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unpad PKCS#7-padded data.
|
||||
*
|
||||
* @param in Input data which includes PKCS#7 padding on end
|
||||
* @param blockSize Block size of algorithm being used
|
||||
*
|
||||
* @return Byte array with PKCS#7 padding removed
|
||||
*
|
||||
* @throws WolfCryptException if input is null, zero length,
|
||||
* or blockSize is invalid
|
||||
*/
|
||||
public static byte[] unPadPKCS7(byte[] in, int blockSize) {
|
||||
|
||||
byte padValue = 0;
|
||||
byte[] unpadded = null;
|
||||
boolean valid = true;
|
||||
|
||||
if (in == null || in.length == 0) {
|
||||
throw new WolfCryptException(
|
||||
"Input array is null or zero length");
|
||||
}
|
||||
|
||||
if (blockSize == 0) {
|
||||
throw new WolfCryptException("Block size is 0");
|
||||
}
|
||||
|
||||
padValue = in[in.length - 1];
|
||||
|
||||
/* verify pad value is less than or equal to block size */
|
||||
if (padValue > (byte)blockSize) {
|
||||
throw new WolfCryptException(
|
||||
"Invalid pad value, larger than block size");
|
||||
}
|
||||
|
||||
/* verify pad bytes are consistent */
|
||||
for (int i = in.length; i > in.length - padValue; i--) {
|
||||
if (in[i - 1] != padValue) {
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
unpadded = new byte[in.length - padValue];
|
||||
System.arraycopy(in, 0, unpadded, 0, in.length - padValue);
|
||||
|
||||
if (!valid) {
|
||||
throw new WolfCryptException(
|
||||
"Invalid PKCS#7 padding, pad bytes not consistent");
|
||||
}
|
||||
|
||||
return unpadded;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -23,8 +23,8 @@ package com.wolfssl.wolfcrypt.test;
|
|||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import javax.crypto.ShortBufferException;
|
||||
|
||||
import org.junit.Assume;
|
||||
|
@ -417,5 +417,104 @@ public class AesTest {
|
|||
enc.releaseNativeStruct();
|
||||
dec.releaseNativeStruct();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPadPKCS7() {
|
||||
|
||||
int padSz = 0;
|
||||
int expectedPadSz = 0;
|
||||
byte[] input = null;
|
||||
byte[] padded = null;
|
||||
byte[] unpadded = null;
|
||||
|
||||
/* Test calculated pad size matches expected for input sizes
|
||||
* from 1 to Aes.BLOCK_SIZE */
|
||||
for (int i = 0; i < Aes.BLOCK_SIZE; i++) {
|
||||
padSz = Aes.getPKCS7PadSize(i + 1, Aes.BLOCK_SIZE);
|
||||
expectedPadSz = Aes.BLOCK_SIZE - ((i + 1) % Aes.BLOCK_SIZE);
|
||||
assertEquals(padSz, expectedPadSz);
|
||||
}
|
||||
|
||||
/* Test pad/unpad of arrays sized 1 to 2 * Aes.BLOCK SIZE bytes,
|
||||
* Fill test arrays with 0xAA */
|
||||
for (int i = 0; i < 2 * Aes.BLOCK_SIZE; i++) {
|
||||
input = new byte[i+1];
|
||||
Arrays.fill(input, 0, input.length, (byte)0xAA);
|
||||
|
||||
padded = Aes.padPKCS7(input, Aes.BLOCK_SIZE);
|
||||
unpadded = Aes.unPadPKCS7(padded, Aes.BLOCK_SIZE);
|
||||
|
||||
assertEquals(input.length, unpadded.length);
|
||||
assertArrayEquals(input, unpadded);
|
||||
}
|
||||
|
||||
/* Test padPKCS7() with null input */
|
||||
try {
|
||||
padded = Aes.padPKCS7(null, Aes.BLOCK_SIZE);
|
||||
fail("null input should throw WolfCryptException");
|
||||
} catch (WolfCryptException e) {
|
||||
/* expected */
|
||||
}
|
||||
|
||||
/* Test padPKCS7() with zero length input */
|
||||
input = new byte[0];
|
||||
padded = Aes.padPKCS7(input, Aes.BLOCK_SIZE);
|
||||
assertNotNull(padded);
|
||||
assertEquals(16, padded.length);
|
||||
|
||||
/* Test padPKCS7() with zero length block size */
|
||||
try {
|
||||
input = new byte[10];
|
||||
padded = Aes.padPKCS7(input, 0);
|
||||
fail("zero length block size should throw WolfCryptException");
|
||||
} catch (WolfCryptException e) {
|
||||
/* expected */
|
||||
}
|
||||
|
||||
/* Test unPadPKCS7() with null input */
|
||||
try {
|
||||
unpadded = Aes.unPadPKCS7(null, Aes.BLOCK_SIZE);
|
||||
fail("null input should throw WolfCryptException");
|
||||
} catch (WolfCryptException e) {
|
||||
/* expected */
|
||||
}
|
||||
|
||||
/* Test unPadPKCS7() with zero length input */
|
||||
try {
|
||||
input = new byte[0];
|
||||
unpadded = Aes.unPadPKCS7(input, Aes.BLOCK_SIZE);
|
||||
fail("zero length input should throw WolfCryptException");
|
||||
} catch (WolfCryptException e) {
|
||||
/* expected */
|
||||
}
|
||||
|
||||
/* Test unPadPKCS7() with zero length block size */
|
||||
try {
|
||||
input = new byte[10];
|
||||
unpadded = Aes.unPadPKCS7(input, 0);
|
||||
fail("zero length block size should throw WolfCryptException");
|
||||
} catch (WolfCryptException e) {
|
||||
/* expected */
|
||||
}
|
||||
|
||||
/* Test unPadPKCS7() with inconsistent pad value */
|
||||
try {
|
||||
padded = Util.h2b("00112233445566778899AABBCC020303");
|
||||
unpadded = Aes.unPadPKCS7(padded, Aes.BLOCK_SIZE);
|
||||
fail("inconsistent padding should throw WolfCryptException");
|
||||
} catch (WolfCryptException e) {
|
||||
/* expected */
|
||||
}
|
||||
|
||||
/* Test unPadPKCS7() with pad value larger than block size */
|
||||
try {
|
||||
padded = Util.h2b("00112233445566778899AABBCC111111");
|
||||
unpadded = Aes.unPadPKCS7(padded, Aes.BLOCK_SIZE);
|
||||
fail("pad value larger than block size should " +
|
||||
"throw WolfCryptException");
|
||||
} catch (WolfCryptException e) {
|
||||
/* expected */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue