Skip to content
This repository was archived by the owner on May 24, 2026. It is now read-only.
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
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,16 +10,20 @@


public class KMCipherImpl extends KMCipher{
Cipher cipher;
javax.crypto.Cipher sunCipher;
short cipherAlg;
short paddingAlg;
short mode;
boolean verificationFlag;
private Cipher cipher;
private javax.crypto.Cipher sunCipher;
private short cipherAlg;
private short paddingAlg;
private short mode;
private boolean verificationFlag;
public static short aes_gcm_decrypt_final_data = 0x00;

KMCipherImpl(Cipher c){
cipher = c;
}
KMCipherImpl(javax.crypto.Cipher c){sunCipher = c;}
KMCipherImpl(javax.crypto.Cipher c){
sunCipher = c;
}

@Override
public short doFinal(byte[] buffer, short startOff, short length, byte[] scratchPad, short i){
Expand All@@ -39,6 +43,15 @@ public short doFinal(byte[] buffer, short startOff, short length, byte[] scratch
}
}else if(cipherAlg == KMCipher.ALG_AES_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 DownExpand Up@@ -93,6 +106,7 @@ 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){
try {
return (short)sunCipher.update(buffer,startOff,length,scratchPad,i);
Expand All@@ -108,7 +122,16 @@ public short update(byte[] buffer, short startOff, short length, byte[] scratchP

@Override
public void updateAAD(byte[] buffer, short startOff, short length) {
try {
sunCipher.updateAAD(buffer,startOff,length);
} catch (IllegalArgumentException e) {
e.printStackTrace();
CryptoException.throwIt(CryptoException.ILLEGAL_VALUE);
} catch (IllegalStateException e) {
CryptoException.throwIt(CryptoException.ILLEGAL_VALUE);
} catch (UnsupportedOperationException e) {
CryptoException.throwIt(CryptoException.ILLEGAL_USE);
}
}

@Override
Expand All@@ -128,4 +151,22 @@ public short getMode() {
public void setMode(short mode) {
this.mode = mode;
}

@Override
public short getCipherProvider() {
return KMCipher.SUN_JCE;
}

@Override
public short getAesGcmOutputSize(short len, short macLength) {
if (sunCipher != null) {
return (short) sunCipher.getOutputSize(len);
} else {
if (mode == KMType.ENCRYPT) {
return (short) (len + macLength);
} else {
return (short) (len - macLength);
}
}
}
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
package com.android.javacard.keymaster;

import java.math.BigInteger;
import java.security.AlgorithmParameters;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SignatureException;
import java.security.interfaces.ECPrivateKey;
import java.security.spec.ECGenParameterSpec;
import java.security.spec.ECParameterSpec;
import java.security.spec.ECPrivateKeySpec;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.InvalidParameterSpecException;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
import java.security.spec.ECGenParameterSpec;
import java.security.spec.ECParameterSpec;
import java.security.spec.ECPoint;
import java.security.spec.ECPrivateKeySpec;
import java.security.spec.ECPublicKeySpec;
import javacard.framework.Util;
import javacard.security.CryptoException;
import javacard.security.Key;
import javacard.security.Signature;


public class KMEcdsa256NoDigestSignature extends Signature {
private java.security.Signature sunSigner;

public KMEcdsa256NoDigestSignature(byte mode, byte[] key, short keyStart, short keyLength){
KeyFactory kf;
try {
sunSigner = java.security.Signature.getInstance("NONEwithECDSA", "SunEC");
kf = KeyFactory.getInstance("EC");
AlgorithmParameters parameters = AlgorithmParameters.getInstance("EC", "SunEC");
//Supported curve secp256r1
parameters.init(new ECGenParameterSpec("secp256r1"));
ECParameterSpec ecParameters = parameters.getParameterSpec(ECParameterSpec.class);
if(mode == Signature.MODE_SIGN) {
byte[] privKey = new byte[keyLength];
for(short i =0; i< keyLength; i++) {
privKey[i] = key[keyStart+i];
}
BigInteger bI = new BigInteger(privKey);
ECPrivateKeySpec prikeyspec = new ECPrivateKeySpec(bI, ecParameters);
ECPrivateKey privkey = (ECPrivateKey) kf.generatePrivate(prikeyspec);
sunSigner.initSign(privkey);
} else {
//Check if the first byte is 04 and remove it.
if(key[keyStart] == 0x04) {
//uncompressed format.
keyStart++;
keyLength--;
}
short i = 0;
byte[] pubx = new byte[keyLength/2];
for(;i < keyLength/2; i++ ) {
pubx[i] = key[keyStart+i];
}
byte[] puby = new byte[keyLength/2];
for(i = 0;i < keyLength/2; i++ ) {
puby[i] = key[keyStart+keyLength/2+i];
}
BigInteger bIX = new BigInteger(pubx);
BigInteger bIY = new BigInteger(puby);
ECPoint point = new ECPoint(bIX, bIY);
ECPublicKeySpec pubkeyspec = new ECPublicKeySpec(point, ecParameters);
ECPublicKey pubkey = (ECPublicKey) kf.generatePublic(pubkeyspec);
sunSigner.initVerify(pubkey);
}
} catch (NoSuchAlgorithmException e) {
CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM);
} catch (NoSuchProviderException e) {
CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM);
} catch(InvalidParameterSpecException e) {
CryptoException.throwIt(CryptoException.INVALID_INIT);
} catch(InvalidKeySpecException e) {
CryptoException.throwIt(CryptoException.INVALID_INIT);
} catch(InvalidKeyException e) {
CryptoException.throwIt(CryptoException.INVALID_INIT);
}
}

@Override
public void init(Key key, byte b) throws CryptoException {

}

@Override
public void init(Key key, byte b, byte[] bytes, short i, short i1) throws CryptoException {

}

@Override
public void setInitialDigest(byte[] bytes, short i, short i1, byte[] bytes1, short i2, short i3) throws CryptoException {

}

@Override
public byte getAlgorithm() {
return 0;
}

@Override
public byte getMessageDigestAlgorithm() {
return 0;
}

@Override
public byte getCipherAlgorithm() {
return 0;
}

@Override
public byte getPaddingAlgorithm() {
return 0;
}

@Override
public short getLength() throws CryptoException {
return 0;
}

@Override
public void update(byte[] message, short msgStart, short messageLength) throws CryptoException {
byte[] msgBytes = new byte[messageLength];
for(int i =0; i< messageLength; i++) {
msgBytes[i] = message[msgStart+i];
}
try {
if(messageLength > 0)
sunSigner.update(msgBytes);
} catch (SignatureException e) {
CryptoException.throwIt(CryptoException.ILLEGAL_VALUE);
}
}

@Override
public short sign(byte[] bytes, short i, short i1, byte[] bytes1, short i2) throws CryptoException {
short len = 0;
try {
update(bytes, i , i1);
byte[] sig = sunSigner.sign();
Util.arrayCopyNonAtomic(sig, (short)0, bytes1, i2, (short)sig.length);
return (short)sig.length;
} catch (SignatureException e) {
// TODO Auto-generated catch block
CryptoException.throwIt(CryptoException.ILLEGAL_VALUE);
}
return len;
}

@Override
public short signPreComputedHash(byte[] bytes, short i, short i1, byte[] bytes1, short i2) throws CryptoException {
return 0;
}

@Override
public boolean verify(byte[] bytes, short i, short i1, byte[] bytes1, short i2, short i3) throws CryptoException {
// Cannot support this method as javacard cipher api does not allow 256 byte for public key
// encryption without padding. It only allows 255 bytes data.
try {
update(bytes, i , i1);
return sunSigner.verify(bytes1, i2, i3);
} catch (SignatureException e) {
// TODO Auto-generated catch block
CryptoException.throwIt(CryptoException.ILLEGAL_VALUE);
}
return false;
}

@Override
public boolean verifyPreComputedHash(byte[] bytes, short i, short i1, byte[] bytes1, short i2, short i3) throws CryptoException {
return false;
}
}
Loading