Skip to content
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

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.android.javacard.keymaster;

public abstract class KMCipher {
/*
public static final byte CIPHER_RSA = 7;
public static final short PAD_PKCS1_OAEP = 9;
public static final short PAD_PKCS1_OAEP_SHA224 = 13;
Expand All @@ -22,6 +23,8 @@ public abstract class KMCipher {
public static final short AES_BLOCK_SIZE = 16;
public static final short DES_BLOCK_SIZE = 8;
public static final short ALG_AES_CTR = -16;

*/
public static final short SUN_JCE = 0xE9;

public abstract short doFinal(byte[] buffer, short startOff, short length, byte[] scratchPad, short i);
Expand All @@ -30,6 +33,10 @@ public abstract class KMCipher {

public abstract void updateAAD(byte[] buffer, short startOff, short length);

public abstract short getBlockMode();

public abstract void setBlockMode(short mode);

public abstract short getPaddingAlgorithm();

public abstract short getCipherAlgorithm();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,10 @@ public class KMCipherImpl extends KMCipher{
private Cipher cipher;
private javax.crypto.Cipher sunCipher;
private short cipherAlg;
private short paddingAlg;
private short padding;
private short mode;
private boolean verificationFlag;
public static short aes_gcm_decrypt_final_data = 0x00;

private short blockMode;
KMCipherImpl(Cipher c){
cipher = c;
}
Expand All @@ -27,8 +26,7 @@ public class KMCipherImpl extends KMCipher{

@Override
public short doFinal(byte[] buffer, short startOff, short length, byte[] scratchPad, short i){
if(cipherAlg == KMCipher.CIPHER_RSA &&
(paddingAlg == KMCipher.PAD_PKCS1_OAEP_SHA256||paddingAlg == KMCipher.PAD_PKCS1_OAEP)){
if(cipherAlg == KMType.RSA && padding == KMType.RSA_OAEP){
try {
return (short)sunCipher.doFinal(buffer,startOff,length,scratchPad,i);
} catch (ShortBufferException e) {
Expand All @@ -41,17 +39,8 @@ public short doFinal(byte[] buffer, short startOff, short length, byte[] scratch
e.printStackTrace();
CryptoException.throwIt(CryptoException.ILLEGAL_VALUE);
}
}else if(cipherAlg == KMCipher.ALG_AES_GCM){
}else if(cipherAlg == KMType.AES && blockMode == KMType.GCM){
try {
/*
if (mode == javax.crypto.Cipher.DECRYPT_MODE) {
short acutalLen = (short)sunCipher.getOutputSize(length);
aes_gcm_decrypt_final_data = KMByteBlob.instance(acutalLen);
return (short)sunCipher.doFinal(buffer,startOff,length,
KMByteBlob.cast(aes_gcm_decrypt_final_data).getBuffer(),
KMByteBlob.cast(aes_gcm_decrypt_final_data).getStartOff());
}
*/
return (short)sunCipher.doFinal(buffer,startOff,length,scratchPad,i);
} catch (AEADBadTagException e) {
e.printStackTrace();
Expand All @@ -65,7 +54,7 @@ public short doFinal(byte[] buffer, short startOff, short length, byte[] scratch
} catch (BadPaddingException e) {
CryptoException.throwIt(CryptoException.ILLEGAL_VALUE);
}
} else if(cipherAlg == KMCipher.ALG_AES_CTR){
} else if(cipherAlg == KMType.AES && blockMode == KMType.CTR){
try {
return (short)sunCipher.doFinal(buffer,startOff,length,scratchPad,i);
} catch (ShortBufferException e) {
Expand All @@ -78,16 +67,62 @@ public short doFinal(byte[] buffer, short startOff, short length, byte[] scratch
e.printStackTrace();
CryptoException.throwIt(CryptoException.ILLEGAL_VALUE);
}
}
else{
} else{
if(cipherAlg == KMType.RSA && padding == KMType.PADDING_NONE && mode == KMType.ENCRYPT ){
// Length cannot be greater then key size according to JcardSim
if(length >= 256) KMException.throwIt(KMError.INVALID_INPUT_LENGTH);
// make input equal to 255 bytes
byte[] tmp = new byte[255];
Util.arrayFillNonAtomic(tmp,(short)0,(short)255, (byte)0);
Util.arrayCopyNonAtomic(
buffer,
startOff,
tmp, (short)(255 - length),length);
startOff = 0;
length = 255;
buffer = tmp;

}else if((cipherAlg == KMType.DES || cipherAlg == KMType.AES) && padding ==KMType.PKCS7 && mode == KMType.ENCRYPT){
byte blkSize = 16;
byte paddingBytes;
short len = length;
if (cipherAlg == KMType.DES) blkSize = 8;
// padding bytes
if (len % blkSize == 0) paddingBytes = blkSize;
else paddingBytes = (byte) (blkSize - (len % blkSize));
// final len with padding
len = (short) (len + paddingBytes);
// intermediate buffer to copy input data+padding
byte[] tmp = new byte[len];
// fill in the padding
Util.arrayFillNonAtomic(tmp, (short) 0, len, paddingBytes);
// copy the input data
Util.arrayCopyNonAtomic(buffer,startOff,tmp,(short)0,length);
buffer = tmp;
length = len;
startOff = 0;
}
short len = cipher.doFinal(buffer, startOff, length, scratchPad, i);
// JCard Sim removes leading zeros during decryption in case of no padding - we add that back.
if (cipherAlg == Cipher.ALG_RSA_NOPAD && mode == Cipher.MODE_DECRYPT && len < 256) {
// JCard Sim removes leading zeros during decryption in case of no padding - so add that back.
if (cipherAlg == KMType.RSA && padding == KMType.PADDING_NONE && mode == KMType.DECRYPT && len < 256) {
byte[] tempBuf = new byte[256];
Util.arrayFillNonAtomic(tempBuf, (short) 0, (short) 256, (byte) 0);
Util.arrayCopyNonAtomic(scratchPad, (short) 0, tempBuf, (short) (i + 256 - len), len);
Util.arrayCopyNonAtomic(tempBuf, (short) 0, scratchPad, i, (short) 256);
len = 256;
}else if((cipherAlg == KMType.AES || cipherAlg == KMType.DES) // PKCS7
&& padding == KMType.PKCS7
&& mode == KMType.DECRYPT){
byte blkSize = 16;
if (cipherAlg == KMType.DES) blkSize = 8;
if(len >0) {
//verify if padding is corrupted.
byte paddingByte = scratchPad[i+len -1];
//padding byte always should be <= block size
if((short)paddingByte > blkSize ||
(short)paddingByte <= 0) KMException.throwIt(KMError.INVALID_ARGUMENT);
len = (short)(len - (short)paddingByte);// remove the padding bytes
}
}
return len;
}
Expand All @@ -106,13 +141,15 @@ public void setCipherAlgorithm(short alg) {

@Override
public short update(byte[] buffer, short startOff, short length, byte[] scratchPad, short i) {
short len = 0;
if(cipherAlg == KMCipher.ALG_AES_GCM || cipherAlg == KMCipher.ALG_AES_CTR){
if(cipherAlg == KMType.AES && (blockMode == KMType.GCM || blockMode == KMType.CTR)){
try {
return (short)sunCipher.update(buffer,startOff,length,scratchPad,i);
} catch (ShortBufferException e) {
e.printStackTrace();
CryptoException.throwIt(CryptoException.ILLEGAL_VALUE);
} catch (IllegalStateException e) {
e.printStackTrace();
CryptoException.throwIt(CryptoException.ILLEGAL_VALUE);
}
} else{
return cipher.update(buffer, startOff, length, scratchPad, i);
Expand All @@ -136,12 +173,22 @@ public void updateAAD(byte[] buffer, short startOff, short length) {

@Override
public short getPaddingAlgorithm() {
return paddingAlg;
return padding;
}

@Override
public void setPaddingAlgorithm(short alg) {
paddingAlg = alg;
padding = alg;
}

@Override
public void setBlockMode(short mode){
blockMode = mode;
}

@Override
public short getBlockMode(){
return blockMode;
}

public short getMode() {
Expand Down Expand Up @@ -169,4 +216,5 @@ public short getAesGcmOutputSize(short len, short macLength) {
}
}
}

}
Loading