diff --git a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMUtils.java b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMUtils.java index cdd86665..65e83415 100644 --- a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMUtils.java +++ b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMUtils.java @@ -70,17 +70,17 @@ public static short convertToDate(short time, byte[] scratchPad, (short) (8 - KMInteger.cast(time).length()), KMInteger.cast(time) .length()); // If the time is less then 1 Jan 2020 then it is an error - if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2020, (short) 0, + if (unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2020, (short) 0, (short) 8) < 0) { KMException.throwIt(KMError.INVALID_ARGUMENT); } if (utcFlag - && KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, + && unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, (short) 0, (short) 8) >= 0) { KMException.throwIt(KMError.INVALID_ARGUMENT); } - if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, (short) 0, + if (unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, (short) 0, (short) 8) < 0) { Util.arrayCopyNonAtomic(firstJan2020, (short) 0, scratchPad, (short) 8, (short) 8); @@ -96,7 +96,7 @@ public static short convertToDate(short time, byte[] scratchPad, (short) 8); } // divide the given time with four yrs msec count - if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, fourYrsMsec, (short) 0, + if (unsignedByteArrayCompare(scratchPad, (short) 0, fourYrsMsec, (short) 0, (short) 8) >= 0) { Util.arrayCopyNonAtomic(fourYrsMsec, (short) 0, scratchPad, (short) 8, (short) 8); @@ -116,9 +116,9 @@ public static short convertToDate(short time, byte[] scratchPad, // if leap year index is 0, then the number of days for the 1st year will be 366 days. // if leap year index is not 0, then the number of days for the 1st year will be 365 days. if (((leapYrIdx == 0) && - (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, leapYearMsec, (short) 0,(short) 8) >= 0)) || + (unsignedByteArrayCompare(scratchPad, (short) 0, leapYearMsec, (short) 0,(short) 8) >= 0)) || ((leapYrIdx != 0) && - (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, yearMsec, (short) 0,(short) 8) >= 0))) { + (unsignedByteArrayCompare(scratchPad, (short) 0, yearMsec, (short) 0,(short) 8) >= 0))) { for (short i = 0; i < 4; i++) { yrsCount++; if (i == leapYrIdx) { @@ -132,12 +132,12 @@ public static short convertToDate(short time, byte[] scratchPad, Util.arrayCopyNonAtomic(scratchPad, (short) 16, scratchPad, (short) 0, (short) 8); if (((short) (i + 1) == leapYrIdx)) { - if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, leapYearMsec, + if (unsignedByteArrayCompare(scratchPad, (short) 0, leapYearMsec, (short) 0, (short) 8) < 0) { break; } } else { - if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, yearMsec, + if (unsignedByteArrayCompare(scratchPad, (short) 0, yearMsec, (short) 0, (short) 8) < 0) { break; } @@ -152,7 +152,7 @@ public static short convertToDate(short time, byte[] scratchPad, yrsCount = (short) (year2051 + yrsCount); // divide the given time with one month msec count - if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, oneMonthMsec, (short) 0, + if (unsignedByteArrayCompare(scratchPad, (short) 0, oneMonthMsec, (short) 0, (short) 8) >= 0) { for (short i = 0; i < 12; i++) { if (i == 1) { @@ -175,7 +175,7 @@ public static short convertToDate(short time, byte[] scratchPad, (short) 8, (short) 8); } - if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, scratchPad, (short) 8, + if (unsignedByteArrayCompare(scratchPad, (short) 0, scratchPad, (short) 8, (short) 8) >= 0) { subtract(scratchPad, (short) 0, (short) 8, (short) 16); Util.arrayCopyNonAtomic(scratchPad, (short) 16, scratchPad, (short) 0, @@ -188,7 +188,7 @@ public static short convertToDate(short time, byte[] scratchPad, } // divide the given time with one day msec count - if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, oneDayMsec, (short) 0, + if (unsignedByteArrayCompare(scratchPad, (short) 0, oneDayMsec, (short) 0, (short) 8) >= 0) { Util.arrayCopyNonAtomic(oneDayMsec, (short) 0, scratchPad, (short) 8, (short) 8); @@ -199,7 +199,7 @@ public static short convertToDate(short time, byte[] scratchPad, } // divide the given time with one hour msec count - if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, oneHourMsec, (short) 0, + if (unsignedByteArrayCompare(scratchPad, (short) 0, oneHourMsec, (short) 0, (short) 8) >= 0) { Util.arrayCopyNonAtomic(oneHourMsec, (short) 0, scratchPad, (short) 8, (short) 8); @@ -209,7 +209,7 @@ public static short convertToDate(short time, byte[] scratchPad, } // divide the given time with one minute msec count - if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, oneMinMsec, (short) 0, + if (unsignedByteArrayCompare(scratchPad, (short) 0, oneMinMsec, (short) 0, (short) 8) >= 0) { Util.arrayCopyNonAtomic(oneMinMsec, (short) 0, scratchPad, (short) 8, (short) 8); @@ -219,7 +219,7 @@ public static short convertToDate(short time, byte[] scratchPad, } // divide the given time with one second msec count - if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, oneSecMsec, (short) 0, + if (unsignedByteArrayCompare(scratchPad, (short) 0, oneSecMsec, (short) 0, (short) 8) >= 0) { Util.arrayCopyNonAtomic(oneSecMsec, (short) 0, scratchPad, (short) 8, (short) 8); @@ -244,7 +244,24 @@ public static short convertToDate(short time, byte[] scratchPad, return KMByteBlob.instance(scratchPad, (short) 0, len); // YYYY } + public static byte unsignedByteArrayCompare(byte[] a1, short offset1, byte[] a2, short offset2, short length) { + byte count = (byte) 0; + short val1 = (short)0; + short val2 = (short)0; + for (; count < length; count++) { + val1 = (short) (a1[(short) (count + offset1)] & 0x00FF); + val2 = (short) (a2[(short) (count + offset2)] & 0x00FF); + + if (val1 < val2) { + return -1; + } + if (val1 > val2) { + return 1; + } + } + return 0; + } public static short numberToString(short number, byte[] scratchPad, short offset) { @@ -294,7 +311,7 @@ public static void copy(byte[] buf, short from, short to) { } public static byte compare(byte[] buf, short lhs, short rhs) { - return KMInteger.unsignedByteArrayCompare(buf, lhs, buf, rhs, (short) 8); + return unsignedByteArrayCompare(buf, lhs, buf, rhs, (short) 8); } public static void shiftLeft(byte[] buf, short start) { diff --git a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMAttestationCertImpl.java b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMAttestationCertImpl.java index 23e7a067..18e67e72 100644 --- a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMAttestationCertImpl.java +++ b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMAttestationCertImpl.java @@ -90,6 +90,7 @@ public class KMAttestationCertImpl implements KMAttestationCert { private static byte[] stack; private static short start; private static short length; + // private static KMRepository repo; private static short uniqueId; private static short attChallenge; private static short notBefore; diff --git a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMCipher.java b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMCipher.java index a5d06a39..3e67ed5e 100644 --- a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMCipher.java +++ b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMCipher.java @@ -24,11 +24,19 @@ 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(); + public abstract void setPaddingAlgorithm(short alg); public abstract void setCipherAlgorithm(short alg); + public abstract short getCipherProvider(); + public abstract short getAesGcmOutputSize(short len, short macLength); } diff --git a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMEcdsa256NoDigestSignature.java b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMEcdsa256NoDigestSignature.java index 56eaba5a..904353b1 100644 --- a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMEcdsa256NoDigestSignature.java +++ b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMEcdsa256NoDigestSignature.java @@ -85,12 +85,18 @@ public KMEcdsa256NoDigestSignature(byte mode, byte[] key, short keyStart, short ECPublicKey pubkey = (ECPublicKey) kf.generatePublic(pubkeyspec); sunSigner.initVerify(pubkey); } - } catch (NoSuchAlgorithmException | NoSuchProviderException e) { + } catch (NoSuchAlgorithmException e) { CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); - } catch(InvalidParameterSpecException | InvalidKeySpecException | InvalidKeyException e) { + } 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 { diff --git a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMJCardSimulator.java b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMJCardSimulator.java index 7e2f0760..0dad8f77 100644 --- a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMJCardSimulator.java +++ b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMJCardSimulator.java @@ -73,6 +73,9 @@ public class KMJCardSimulator implements KMSEProvider { public static final byte[] aesICV = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; private static final short CERT_CHAIN_MAX_SIZE = 2500;//First 2 bytes for length. private static final short RSA_KEY_SIZE = 256; + + + public static boolean jcardSim = false; private static Signature kdf; private static Signature hmacSignature; @@ -114,11 +117,13 @@ public KMJCardSimulator() { jCardSimulator = this; } + public KeyPair createRsaKeyPair() { KeyPair rsaKeyPair = new KeyPair(KeyPair.ALG_RSA, KeyBuilder.LENGTH_RSA_2048); rsaKeyPair.genKeyPair(); return rsaKeyPair; } + public RSAPrivateKey createRsaKey(byte[] modBuffer, short modOff, short modLength, byte[] privBuffer, short privOff, short privLength) { @@ -127,13 +132,16 @@ public RSAPrivateKey createRsaKey(byte[] modBuffer, short modOff, short modLengt privKey.setExponent(privBuffer, privOff, privLength); privKey.setModulus(modBuffer, modOff, modLength); return privKey; + } + public KeyPair createECKeyPair() { KeyPair ecKeyPair = new KeyPair(KeyPair.ALG_EC_FP, KeyBuilder.LENGTH_EC_FP_256); ecKeyPair.genKeyPair(); return ecKeyPair; } + public ECPrivateKey createEcKey(byte[] privBuffer, short privOff, short privLength) { KeyPair ecKeyPair = new KeyPair(KeyPair.ALG_EC_FP, KeyBuilder.LENGTH_EC_FP_256); @@ -141,6 +149,7 @@ public ECPrivateKey createEcKey(byte[] privBuffer, short privOff, short privLeng privKey.setS(privBuffer,privOff, privLength); return privKey; } + public AESKey createAESKey(short keysize) { byte[] rndNum = new byte[(short) (keysize/8)]; @@ -160,11 +169,13 @@ public AESKey createAESKey(byte[] buf, short startOff, short length) { return key; } + public DESKey createTDESKey() { byte[] rndNum = new byte[24]; newRandomNumber(rndNum, (short) 0, (short)rndNum.length); return createTDESKey(rndNum, (short)0, (short)rndNum.length); } + public DESKey createTDESKey(byte[] secretBuffer, short secretOff, short secretLength) { DESKey triDesKey = @@ -172,6 +183,7 @@ public DESKey createTDESKey(byte[] secretBuffer, short secretOff, short secretLe triDesKey.setKey(secretBuffer, secretOff); return triDesKey; } + public HMACKey createHMACKey(short keysize) { if((keysize % 8 != 0) || !(keysize >= 64 && keysize <= 512)){ @@ -248,13 +260,13 @@ public void createAsymmetricKey(byte alg, byte[] privKeyBuf, short privKeyStart, public boolean importSymmetricKey(byte alg, short keysize, byte[] buf, short startOff, short length) { switch(alg){ case KMType.AES: - createAESKey(buf,startOff,length); + AESKey aesKey = createAESKey(buf,startOff,length); break; case KMType.DES: - createTDESKey(buf,startOff,length); + DESKey desKey = createTDESKey(buf,startOff,length); break; case KMType.HMAC: - createHMACKey(buf,startOff,length); + HMACKey hmacKey = createHMACKey(buf,startOff,length); break; default: CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); @@ -267,10 +279,10 @@ public boolean importSymmetricKey(byte alg, short keysize, byte[] buf, short sta public boolean importAsymmetricKey(byte alg, byte[] privKeyBuf, short privKeyStart, short privKeyLength, byte[] pubModBuf, short pubModStart, short pubModLength) { switch (alg){ case KMType.RSA: - createRsaKey(pubModBuf,pubModStart,pubModLength,privKeyBuf,privKeyStart,privKeyLength); + RSAPrivateKey rsaKey = createRsaKey(pubModBuf,pubModStart,pubModLength,privKeyBuf,privKeyStart,privKeyLength); break; case KMType.EC: - createEcKey(privKeyBuf,privKeyStart,privKeyLength); + ECPrivateKey ecPrivKey = createEcKey(privKeyBuf,privKeyStart,privKeyLength); break; default: CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); @@ -352,7 +364,13 @@ public short aesGCMEncrypt( byte[] outputBuf = new byte[cipher.getOutputSize(secretLen)]; try { len = (short)(cipher.doFinal(secret,secretStart,secretLen,outputBuf,(short)0)); - } catch (ShortBufferException | IllegalBlockSizeException | BadPaddingException e) { + } catch (ShortBufferException e) { + e.printStackTrace(); + CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); + } catch (IllegalBlockSizeException e) { + e.printStackTrace(); + CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); + } catch (BadPaddingException e) { e.printStackTrace(); CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); } @@ -440,7 +458,13 @@ public boolean aesGCMDecrypt( } catch (AEADBadTagException e) { e.printStackTrace(); return false; - } catch (ShortBufferException | IllegalBlockSizeException | BadPaddingException e) { + } catch (ShortBufferException e) { + e.printStackTrace(); + CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); + } catch (IllegalBlockSizeException e) { + e.printStackTrace(); + CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); + } catch (BadPaddingException e) { e.printStackTrace(); CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); } @@ -663,10 +687,19 @@ private KMCipher createRsaOAEP256Cipher(byte mode,byte digest, } catch (NoSuchAlgorithmException e) { e.printStackTrace(); CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); - } catch (InvalidKeySpecException | InvalidAlgorithmParameterException | NoSuchPaddingException e) { + } catch (InvalidKeySpecException e) { e.printStackTrace(); CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); - } catch (InvalidKeyException | NoSuchProviderException e) { + } catch (InvalidKeyException e) { + e.printStackTrace(); + CryptoException.throwIt(CryptoException.INVALID_INIT); + } catch (InvalidAlgorithmParameterException e) { + e.printStackTrace(); + CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); + } catch (NoSuchPaddingException e) { + e.printStackTrace(); + CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); + } catch (NoSuchProviderException e) { e.printStackTrace(); CryptoException.throwIt(CryptoException.INVALID_INIT); } @@ -730,7 +763,13 @@ public Signature createEcSigner(short digest, byte[] secret, short secretStart, return ecSigner; } + + public KMCipher createSymmetricCipher( + short cipherAlg, short mode, short blockMode, short padding, byte[] secret, short secretStart, short secretLength) { + return createSymmetricCipher(cipherAlg, mode, blockMode, padding, secret,secretStart,secretLength,null,(short)0,(short)0); + } + public KMCipher createSymmetricCipher(short alg, short purpose, short blockMode, short padding, byte[] secret, short secretStart, short secretLength, byte[] ivBuffer, short ivStart, short ivLength) { @@ -910,6 +949,7 @@ private KMCipher createAesCtrCipherNoPad(short mode, byte[] secret, short secret return ret; } + public Signature createHmacSignerVerifier(short purpose, short digest, byte[] secret, short secretStart, short secretLength) { short alg = Signature.ALG_HMAC_SHA_256; if(digest != KMType.SHA2_256) CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); @@ -919,6 +959,7 @@ public Signature createHmacSignerVerifier(short purpose, short digest, byte[] se hmacSignerVerifier.init(key,(byte)purpose); return hmacSignerVerifier; } + public KMCipher createAesGcmCipher(short mode, short tagLen, byte[] secret, short secretStart, short secretLength, byte[] ivBuffer, short ivStart, short ivLength) { @@ -1174,7 +1215,7 @@ public KMMasterKey createMasterKey(short keySizeBits) { getTrueRandomNumber(keyData, (short) 0, keyLen); masterKey.setKey(keyData, (short) 0); } - return masterKey; + return (KMMasterKey) masterKey; } @Override @@ -1186,7 +1227,7 @@ public KMAttestationKey createAttestationKey(byte[] keyData, short offset, attestationKey = new KMECPrivateKey(ecKeyPair); } attestationKey.setS(keyData, offset, length); - return attestationKey; + return (KMAttestationKey) attestationKey; } @Override @@ -1201,7 +1242,7 @@ public KMPreSharedKey createPresharedKey(byte[] keyData, short offset, short len preSharedKey = new KMHmacKey(key); } preSharedKey.setKey(keyData, offset, length); - return preSharedKey; + return (KMPreSharedKey) preSharedKey; } @Override diff --git a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMRsa2048NoDigestSignature.java b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMRsa2048NoDigestSignature.java index de97d02c..fc953d73 100644 --- a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMRsa2048NoDigestSignature.java +++ b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMRsa2048NoDigestSignature.java @@ -121,7 +121,7 @@ private boolean isValidData(byte[] buf, short start, short len) { if (padding == KMType.PADDING_NONE) { if (len > 256) return false; else if (len == 256) { - short v = KMInteger.unsignedByteArrayCompare(buf, start, rsaModulus, (short) 0, len); + short v = KMUtils.unsignedByteArrayCompare(buf, start, rsaModulus, (short) 0, len); if (v > 0) return false; } } else {//pkcs1 no digest diff --git a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMUtils.java b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMUtils.java index c494bb34..65e83415 100644 --- a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMUtils.java +++ b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMUtils.java @@ -52,6 +52,7 @@ public class KMUtils { public static final short year2051 = 2051; public static final short year2020 = 2020; + // -------------------------------------- public static short convertToDate(short time, byte[] scratchPad, boolean utcFlag) { @@ -69,17 +70,17 @@ public static short convertToDate(short time, byte[] scratchPad, (short) (8 - KMInteger.cast(time).length()), KMInteger.cast(time) .length()); // If the time is less then 1 Jan 2020 then it is an error - if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2020, (short) 0, + if (unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2020, (short) 0, (short) 8) < 0) { KMException.throwIt(KMError.INVALID_ARGUMENT); } if (utcFlag - && KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, + && unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, (short) 0, (short) 8) >= 0) { KMException.throwIt(KMError.INVALID_ARGUMENT); } - if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, (short) 0, + if (unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, (short) 0, (short) 8) < 0) { Util.arrayCopyNonAtomic(firstJan2020, (short) 0, scratchPad, (short) 8, (short) 8); @@ -95,7 +96,7 @@ public static short convertToDate(short time, byte[] scratchPad, (short) 8); } // divide the given time with four yrs msec count - if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, fourYrsMsec, (short) 0, + if (unsignedByteArrayCompare(scratchPad, (short) 0, fourYrsMsec, (short) 0, (short) 8) >= 0) { Util.arrayCopyNonAtomic(fourYrsMsec, (short) 0, scratchPad, (short) 8, (short) 8); @@ -115,9 +116,9 @@ public static short convertToDate(short time, byte[] scratchPad, // if leap year index is 0, then the number of days for the 1st year will be 366 days. // if leap year index is not 0, then the number of days for the 1st year will be 365 days. if (((leapYrIdx == 0) && - (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, leapYearMsec, (short) 0,(short) 8) >= 0)) || + (unsignedByteArrayCompare(scratchPad, (short) 0, leapYearMsec, (short) 0,(short) 8) >= 0)) || ((leapYrIdx != 0) && - (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, yearMsec, (short) 0,(short) 8) >= 0))) { + (unsignedByteArrayCompare(scratchPad, (short) 0, yearMsec, (short) 0,(short) 8) >= 0))) { for (short i = 0; i < 4; i++) { yrsCount++; if (i == leapYrIdx) { @@ -131,12 +132,12 @@ public static short convertToDate(short time, byte[] scratchPad, Util.arrayCopyNonAtomic(scratchPad, (short) 16, scratchPad, (short) 0, (short) 8); if (((short) (i + 1) == leapYrIdx)) { - if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, leapYearMsec, + if (unsignedByteArrayCompare(scratchPad, (short) 0, leapYearMsec, (short) 0, (short) 8) < 0) { break; } } else { - if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, yearMsec, + if (unsignedByteArrayCompare(scratchPad, (short) 0, yearMsec, (short) 0, (short) 8) < 0) { break; } @@ -151,7 +152,7 @@ public static short convertToDate(short time, byte[] scratchPad, yrsCount = (short) (year2051 + yrsCount); // divide the given time with one month msec count - if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, oneMonthMsec, (short) 0, + if (unsignedByteArrayCompare(scratchPad, (short) 0, oneMonthMsec, (short) 0, (short) 8) >= 0) { for (short i = 0; i < 12; i++) { if (i == 1) { @@ -174,7 +175,7 @@ public static short convertToDate(short time, byte[] scratchPad, (short) 8, (short) 8); } - if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, scratchPad, (short) 8, + if (unsignedByteArrayCompare(scratchPad, (short) 0, scratchPad, (short) 8, (short) 8) >= 0) { subtract(scratchPad, (short) 0, (short) 8, (short) 16); Util.arrayCopyNonAtomic(scratchPad, (short) 16, scratchPad, (short) 0, @@ -187,7 +188,7 @@ public static short convertToDate(short time, byte[] scratchPad, } // divide the given time with one day msec count - if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, oneDayMsec, (short) 0, + if (unsignedByteArrayCompare(scratchPad, (short) 0, oneDayMsec, (short) 0, (short) 8) >= 0) { Util.arrayCopyNonAtomic(oneDayMsec, (short) 0, scratchPad, (short) 8, (short) 8); @@ -198,7 +199,7 @@ public static short convertToDate(short time, byte[] scratchPad, } // divide the given time with one hour msec count - if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, oneHourMsec, (short) 0, + if (unsignedByteArrayCompare(scratchPad, (short) 0, oneHourMsec, (short) 0, (short) 8) >= 0) { Util.arrayCopyNonAtomic(oneHourMsec, (short) 0, scratchPad, (short) 8, (short) 8); @@ -208,7 +209,7 @@ public static short convertToDate(short time, byte[] scratchPad, } // divide the given time with one minute msec count - if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, oneMinMsec, (short) 0, + if (unsignedByteArrayCompare(scratchPad, (short) 0, oneMinMsec, (short) 0, (short) 8) >= 0) { Util.arrayCopyNonAtomic(oneMinMsec, (short) 0, scratchPad, (short) 8, (short) 8); @@ -218,7 +219,7 @@ public static short convertToDate(short time, byte[] scratchPad, } // divide the given time with one second msec count - if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, oneSecMsec, (short) 0, + if (unsignedByteArrayCompare(scratchPad, (short) 0, oneSecMsec, (short) 0, (short) 8) >= 0) { Util.arrayCopyNonAtomic(oneSecMsec, (short) 0, scratchPad, (short) 8, (short) 8); @@ -243,6 +244,25 @@ public static short convertToDate(short time, byte[] scratchPad, return KMByteBlob.instance(scratchPad, (short) 0, len); // YYYY } + public static byte unsignedByteArrayCompare(byte[] a1, short offset1, byte[] a2, short offset2, short length) { + byte count = (byte) 0; + short val1 = (short)0; + short val2 = (short)0; + + for (; count < length; count++) { + val1 = (short) (a1[(short) (count + offset1)] & 0x00FF); + val2 = (short) (a2[(short) (count + offset2)] & 0x00FF); + + if (val1 < val2) { + return -1; + } + if (val1 > val2) { + return 1; + } + } + return 0; + } + public static short numberToString(short number, byte[] scratchPad, short offset) { byte zero = 0x30; @@ -291,7 +311,7 @@ public static void copy(byte[] buf, short from, short to) { } public static byte compare(byte[] buf, short lhs, short rhs) { - return KMInteger.unsignedByteArrayCompare(buf, lhs, buf, rhs, (short) 8); + return unsignedByteArrayCompare(buf, lhs, buf, rhs, (short) 8); } public static void shiftLeft(byte[] buf, short start) { diff --git a/Applet/src/com/android/javacard/keymaster/KMByteBlob.java b/Applet/src/com/android/javacard/keymaster/KMByteBlob.java index eb065e10..28b916db 100644 --- a/Applet/src/com/android/javacard/keymaster/KMByteBlob.java +++ b/Applet/src/com/android/javacard/keymaster/KMByteBlob.java @@ -115,4 +115,10 @@ public boolean isValid() { } return true; } + + public void decrementLength(short len) { + short length = Util.getShort(heap, (short) (instPtr + 1)); + length = (short) (length - len); + Util.setShort(heap, (short) (instPtr + 1), length); + } } diff --git a/Applet/src/com/android/javacard/keymaster/KMEncoder.java b/Applet/src/com/android/javacard/keymaster/KMEncoder.java index b4055f04..685ba468 100644 --- a/Applet/src/com/android/javacard/keymaster/KMEncoder.java +++ b/Applet/src/com/android/javacard/keymaster/KMEncoder.java @@ -38,6 +38,7 @@ public class KMEncoder { private static final byte UINT64_LENGTH = (byte) 0x1B; private static final short TINY_PAYLOAD = 0x17; private static final short SHORT_PAYLOAD = 0x100; + //TODO make this static. private byte[] buffer; private short startOff; private short length; @@ -72,6 +73,7 @@ public short encode(short object, byte[] buffer, short startOff) { }else{ this.length = (short)buffer.length; } + //this.length = (short)(startOff + length); push(object); encode(); return (short)(this.startOff - startOff); diff --git a/Applet/src/com/android/javacard/keymaster/KMEnumArrayTag.java b/Applet/src/com/android/javacard/keymaster/KMEnumArrayTag.java index 98ec05f7..37e23286 100644 --- a/Applet/src/com/android/javacard/keymaster/KMEnumArrayTag.java +++ b/Applet/src/com/android/javacard/keymaster/KMEnumArrayTag.java @@ -279,4 +279,12 @@ public boolean isValidPurpose(byte alg) { } return true; } + + public boolean isValidBlockMode(byte alg) { + if (alg == KMType.AES || alg == KMType.DES) { + return true; + } else { + return false; + } + } } diff --git a/Applet/src/com/android/javacard/keymaster/KMError.java b/Applet/src/com/android/javacard/keymaster/KMError.java index 0a52da0a..83eb8c7c 100644 --- a/Applet/src/com/android/javacard/keymaster/KMError.java +++ b/Applet/src/com/android/javacard/keymaster/KMError.java @@ -21,61 +21,82 @@ */ public class KMError { public static final short OK = 0; - + public static final short ROOT_OF_TRUST_ALREADY_SET = 1; public static final short UNSUPPORTED_PURPOSE = 2; public static final short INCOMPATIBLE_PURPOSE = 3; public static final short UNSUPPORTED_ALGORITHM = 4; public static final short INCOMPATIBLE_ALGORITHM = 5; public static final short UNSUPPORTED_KEY_SIZE = 6; - + public static final short UNSUPPORTED_BLOCK_MODE = 7; public static final short INCOMPATIBLE_BLOCK_MODE = 8; public static final short UNSUPPORTED_MAC_LENGTH = 9; public static final short UNSUPPORTED_PADDING_MODE = 10; public static final short INCOMPATIBLE_PADDING_MODE = 11; public static final short UNSUPPORTED_DIGEST = 12; public static final short INCOMPATIBLE_DIGEST = 13; - + public static final short INVALID_EXPIRATION_TIME = 14; + public static final short INVALID_USER_ID = 15; + public static final short INVALID_AUTHORIZATION_TIMEOUT = 16; + public static final short UNSUPPORTED_KEY_FORMAT = 17; + public static final short INCOMPATIBLE_KEY_FORMAT = 18; public static final short UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM = 19; - - /** For PKCS8 & PKCS12 */ + /** For PKCS8 & PKCS12 */ + public static final short UNSUPPORTED_KEY_VERIFICATION_ALGORITHM = 20; + /** For PKCS8 & PKCS12 */ public static final short INVALID_INPUT_LENGTH = 21; - + public static final short KEY_EXPORT_OPTIONS_INVALID = 22; + public static final short DELEGATION_NOT_ALLOWED = 23; + public static final short KEY_NOT_YET_VALID = 24; + public static final short KEY_EXPIRED = 25; public static final short KEY_USER_NOT_AUTHENTICATED = 26; - + public static final short OUTPUT_PARAMETER_NULL = 27; public static final short INVALID_OPERATION_HANDLE = 28; - + public static final short INSUFFICIENT_BUFFER_SPACE = 29; public static final short VERIFICATION_FAILED = 30; public static final short TOO_MANY_OPERATIONS = 31; + public static final short UNEXPECTED_NULL_POINTER = 32; public static final short INVALID_KEY_BLOB = 33; - + public static final short IMPORTED_KEY_NOT_ENCRYPTED = 34; + public static final short IMPORTED_KEY_DECRYPTION_FAILED = 35; + public static final short IMPORTED_KEY_NOT_SIGNED = 36; + public static final short IMPORTED_KEY_VERIFICATION_FAILED = 37; public static final short INVALID_ARGUMENT = 38; public static final short UNSUPPORTED_TAG = 39; public static final short INVALID_TAG = 40; - + public static final short MEMORY_ALLOCATION_FAILED = 41; public static final short IMPORT_PARAMETER_MISMATCH = 44; + public static final short SECURE_HW_ACCESS_DENIED = 45; public static final short OPERATION_CANCELLED = 46; - + public static final short CONCURRENT_ACCESS_CONFLICT = 47; + public static final short SECURE_HW_BUSY = 48; + public static final short SECURE_HW_COMMUNICATION_FAILED = 49; + public static final short UNSUPPORTED_EC_FIELD = 50; public static final short MISSING_NONCE = 51; public static final short INVALID_NONCE = 52; public static final short MISSING_MAC_LENGTH = 53; - + public static final short KEY_RATE_LIMIT_EXCEEDED = 54; public static final short CALLER_NONCE_PROHIBITED = 55; - + public static final short KEY_MAX_OPS_EXCEEDED = 56; public static final short INVALID_MAC_LENGTH = 57; public static final short MISSING_MIN_MAC_LENGTH = 58; public static final short UNSUPPORTED_MIN_MAC_LENGTH = 59; - + public static final short UNSUPPORTED_KDF = 60; public static final short UNSUPPORTED_EC_CURVE = 61; public static final short KEY_REQUIRES_UPGRADE = 62; - + public static final short ATTESTATION_CHALLENGE_MISSING = 63; + public static final short KEYMASTER_NOT_CONFIGURED = 64; public static final short ATTESTATION_APPLICATION_ID_MISSING = 65; + public static final short CANNOT_ATTEST_IDS = 66; public static final short ROLLBACK_RESISTANCE_UNAVAILABLE = 67; - + public static final short HARDWARE_TYPE_UNAVAILABLE = 68; + public static final short PROOF_OF_PRESENCE_REQUIRED = 69; + public static final short CONCURRENT_PROOF_OF_PRESENCE_REQUESTED = 70; + public static final short NO_USER_CONFIRMATION = 71; public static final short DEVICE_LOCKED = 72; public static final short EARLY_BOOT_ENDED = 73; - public static final short UNIMPLEMENTED = 100; + public static final short VERSION_MISMATCH = 101; public static final short UNKNOWN_ERROR = 1000; //Extended errors diff --git a/Applet/src/com/android/javacard/keymaster/KMInteger.java b/Applet/src/com/android/javacard/keymaster/KMInteger.java index 44a0779a..18944e4d 100644 --- a/Applet/src/com/android/javacard/keymaster/KMInteger.java +++ b/Applet/src/com/android/javacard/keymaster/KMInteger.java @@ -162,30 +162,10 @@ public static short compare(short num1, short num2){ KMInteger.cast(num1).getValue(repository.getHeap(),(short)(num1Buf+(short)(8-len)),len); len = KMInteger.cast(num2).length(); KMInteger.cast(num2).getValue(repository.getHeap(),(short)(num2Buf+(short)(8-len)),len); - return KMInteger.unsignedByteArrayCompare( + return KMUtils.unsignedByteArrayCompare( repository.getHeap(), num1Buf, repository.getHeap(), num2Buf, (short)8); } - - public static byte unsignedByteArrayCompare(byte[] a1, short offset1, byte[] a2, short offset2, short length) { - byte count = (byte) 0; - short val1 = (short)0; - short val2 = (short)0; - - for (; count < length; count++) { - val1 = (short) (a1[(short) (count + offset1)] & 0x00FF); - val2 = (short) (a2[(short) (count + offset2)] & 0x00FF); - - if (val1 < val2) { - return -1; - } - if (val1 > val2) { - return 1; - } - } - return 0; - } - } diff --git a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java index 3942a891..e1e8214d 100644 --- a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java +++ b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java @@ -3481,7 +3481,7 @@ private void checkVersionAndPatchLevel(byte[] scratchPad) { if (tmpVariables[0] != KMType.INVALID_VALUE) { tmpVariables[1] = repository.getOsVersion(); tmpVariables[1] = - KMInteger.unsignedByteArrayCompare( + KMUtils.unsignedByteArrayCompare( KMInteger.cast(tmpVariables[1]).getBuffer(), KMInteger.cast(tmpVariables[1]).getStartOff(), scratchPad, @@ -3500,7 +3500,7 @@ private void checkVersionAndPatchLevel(byte[] scratchPad) { if (tmpVariables[0] != KMType.INVALID_VALUE) { tmpVariables[1] = repository.getOsPatch(); tmpVariables[1] = - KMInteger.unsignedByteArrayCompare( + KMUtils.unsignedByteArrayCompare( KMInteger.cast(tmpVariables[1]).getBuffer(), KMInteger.cast(tmpVariables[1]).getStartOff(), scratchPad, diff --git a/Applet/src/com/android/javacard/keymaster/KMOperationState.java b/Applet/src/com/android/javacard/keymaster/KMOperationState.java index 6d033443..6ea96941 100644 --- a/Applet/src/com/android/javacard/keymaster/KMOperationState.java +++ b/Applet/src/com/android/javacard/keymaster/KMOperationState.java @@ -41,7 +41,7 @@ public class KMOperationState { // short type private static final byte KEY_SIZE = 6; private static final byte MAC_LENGTH = 8; - + // Handle - currently this is short private static final byte OP_HANDLE = 10; // Auth time 64 bits private static final byte AUTH_TIME = 12; diff --git a/Applet/src/com/android/javacard/keymaster/KMSEProvider.java b/Applet/src/com/android/javacard/keymaster/KMSEProvider.java index 0719d04b..a057eb9e 100644 --- a/Applet/src/com/android/javacard/keymaster/KMSEProvider.java +++ b/Applet/src/com/android/javacard/keymaster/KMSEProvider.java @@ -220,7 +220,7 @@ boolean aesGCMDecrypt( * This is a oneshot operation that performs key derivation function using cmac kdf (CKDF) as * defined in android keymaster hal definition. * - * @param hmacKey instance of pre-shared key. + * @param instance of pre-shared key. * @param label is the label to be used for ckdf. * @param labelStart is the start of label. * @param labelLen is the length of the label. @@ -269,7 +269,7 @@ short hmacSign( * This is a oneshot operation that signs the data using hmac algorithm. * This is used to derive the key, which is used to encrypt the keyblob. * - * @param masterkey instance of masterkey. + * @param instance of masterkey. * @param data is the buffer containing data to be signed. * @param dataStart is the start of the data. * @param dataLength is the length of the data. @@ -344,7 +344,7 @@ short rsaDecipherOAEP256( /** * This is a oneshot operation that signs the data using EC private key. * - * @param ecPrivKey instance of KMAttestationKey. + * @param instance of KMAttestationKey. * @param inputDataBuf is the buffer of the input data. * @param inputDataStart is the start of the input data buffer. * @param inputDataLength is the length of the inpur data buffer in bytes. diff --git a/Applet/src/com/android/javacard/keymaster/KMType.java b/Applet/src/com/android/javacard/keymaster/KMType.java index 53442440..4d81de45 100644 --- a/Applet/src/com/android/javacard/keymaster/KMType.java +++ b/Applet/src/com/android/javacard/keymaster/KMType.java @@ -41,6 +41,7 @@ public abstract class KMType { public static final byte HW_AUTH_TOKEN_TYPE = 0x08; public static final byte VERIFICATION_TOKEN_TYPE = 0x09; public static final byte HMAC_SHARING_PARAM_TYPE = 0x0A; + public static final byte X509_CERT = 0x0B; // Tag Types public static final short INVALID_TAG = 0x0000; public static final short ENUM_TAG = 0x1000; @@ -50,6 +51,7 @@ public abstract class KMType { public static final short ULONG_TAG = 0x5000; public static final short DATE_TAG = 0x6000; public static final short BOOL_TAG = 0x7000; + public static final short BIGNUM_TAG = (short) 0x8000; public static final short BYTES_TAG = (short) 0x9000; public static final short ULONG_ARRAY_TAG = (short) 0xA000; public static final short TAG_TYPE_MASK = (short) 0xF000; @@ -269,6 +271,7 @@ public abstract class KMType { // Confirmation Token public static final short CONFIRMATION_TOKEN = (short) 0x03ED; + public static final short LENGTH_FROM_PDU = (short) 0xFFFF; public static final byte NO_VALUE = (byte) 0xff;