diff --git a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAndroidSEProvider.java b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAndroidSEProvider.java index 6a5a0671..78b90b57 100644 --- a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAndroidSEProvider.java +++ b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAndroidSEProvider.java @@ -112,6 +112,7 @@ public class KMAndroidSEProvider implements KMSEProvider { public static final byte KEYSIZE_128_OFFSET = 0x00; public static final byte KEYSIZE_256_OFFSET = 0x01; public static final short TMP_ARRAY_SIZE = 256; + private static final short RSA_KEY_SIZE = 256; public static final short CERT_CHAIN_MAX_SIZE = 2500;//First 2 bytes for length. final byte[] CIPHER_ALGS = { @@ -532,13 +533,27 @@ public void createAsymmetricKey(byte alg, byte[] privKeyBuf, short pubModStart, short pubModLength, short[] lengths) { switch (alg) { case KMType.RSA: + if (RSA_KEY_SIZE != privKeyLength || RSA_KEY_SIZE != pubModLength) { + CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); + } KeyPair rsaKey = createRsaKeyPair(); RSAPrivateKey privKey = (RSAPrivateKey) rsaKey.getPrivate(); - lengths[0] = privKey.getExponent(privKeyBuf, privKeyStart); - lengths[1] = privKey.getModulus(pubModBuf, pubModStart); - if (lengths[0] > privKeyLength || lengths[1] > pubModLength) { + //Copy exponent. + Util.arrayFillNonAtomic(tmpArray, (short) 0, RSA_KEY_SIZE, (byte) 0); + lengths[0] = privKey.getExponent(tmpArray, (short)0); + if (lengths[0] > privKeyLength) CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); - } + Util.arrayFillNonAtomic(privKeyBuf, privKeyStart, privKeyLength, (byte)0); + Util.arrayCopyNonAtomic(tmpArray, (short)0, + privKeyBuf, (short)(privKeyStart + privKeyLength - lengths[0]), lengths[0]); + //Copy modulus + Util.arrayFillNonAtomic(tmpArray, (short) 0, RSA_KEY_SIZE, (byte) 0); + lengths[1] = privKey.getModulus(tmpArray, (short)0); + if (lengths[1] > pubModLength) + CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); + Util.arrayFillNonAtomic(pubModBuf, pubModStart, pubModLength, (byte)0); + Util.arrayCopyNonAtomic(tmpArray, (short)0, + pubModBuf, (short)(pubModStart + pubModLength - lengths[1]), lengths[1]); break; case KMType.EC: KeyPair ecKey = createECKeyPair(); diff --git a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAttestationCertImpl.java b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAttestationCertImpl.java index 6025feef..637a2fba 100644 --- a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAttestationCertImpl.java +++ b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAttestationCertImpl.java @@ -127,7 +127,6 @@ public static KMAttestationCert instance(boolean rsaCert) { } private static void init() { - // if (repo == null) repo = KMRepository.instance(); stack = null; stackPtr = 0; certStart = 0; @@ -283,7 +282,6 @@ private static void pushTbsCert(boolean rsaCert) { pushBytes(X509Subject, (short) 0, (short) X509Subject.length); pushValidity(); // issuer - der encoded - // pushBytes(repo.getCertDataBuffer(), repo.getIssuer(), repo.getIssuerLen()); pushBytes( KMByteBlob.cast(issuer).getBuffer(), KMByteBlob.cast(issuer).getStartOff(), @@ -304,23 +302,6 @@ private static void pushTbsCert(boolean rsaCert) { private static void pushExtensions() { short last = stackPtr; - // byte keyusage = 0; - // byte unusedBits = 8; - /* - if (KMEnumArrayTag.contains(KMType.PURPOSE, KMType.SIGN, hwParams)) { - keyusage = (byte) (keyusage | keyUsageSign); - unusedBits = 7; - } - if (KMEnumArrayTag.contains(KMType.PURPOSE, KMType.WRAP_KEY, hwParams)) { - keyusage = (byte) (keyusage | keyUsageKeyEncipher); - unusedBits = 5; - } - if (KMEnumArrayTag.contains(KMType.PURPOSE, KMType.DECRYPT, hwParams)) { - keyusage = (byte) (keyusage | keyUsageDataEncipher); - unusedBits = 4; - } - - */ if (keyUsage != 0) pushKeyUsage(keyUsage, unusedBits); pushKeyDescription(); pushSequenceHeader((short) (last - stackPtr)); @@ -565,7 +546,6 @@ private static void pushTag(short tag) { private static void pushRoT() { short last = stackPtr; // verified boot hash - // pushOctetString(repo.verifiedBootHash, (short) 0, (short) repo.verifiedBootHash.length); pushOctetString( KMByteBlob.cast(verifiedHash).getBuffer(), KMByteBlob.cast(verifiedHash).getStartOff(), @@ -670,7 +650,6 @@ private static void pushEnumTag(short tagId, byte val) { private static void pushIntegerTag(short tagId, byte[] buf, short start, short len) { short last = stackPtr; pushInteger(buf, start, len); - // pushIntegerHeader((short) (last - stackPtr)); pushTagIdHeader(tagId, (short) (last - stackPtr)); } // Ignore leading zeros. Only Unsigned Integers are required hence if MSB is set then add 0x00 diff --git a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMUtils.java b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMUtils.java index 7b4352f8..65e83415 100644 --- a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMUtils.java +++ b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMUtils.java @@ -347,29 +347,6 @@ public static void shiftRight(byte[] buf, short start) { } } - - // num1 must be greater then or equal to num2 and both must be positive - /*private short subtractIntegers(short num1, short num2) { - short buf = - repository.alloc((short)24); byte[] scratchPad = repository.getHeap(); - Util.arrayFillNonAtomic(scratchPad, buf, (short) 24, (byte) 0); - Util.arrayCopyNonAtomic(KMInteger.cast(num1).getBuffer(), - KMInteger.cast(num1).getStartOff(), scratchPad, - (short) (buf + 8 - KMInteger.cast(num1).length()), - KMInteger.cast(num1).length()); - Util.arrayCopyNonAtomic(KMInteger.cast(num2).getBuffer(), - KMInteger.cast(num2).getStartOff(), scratchPad, - (short) (buf + 16 - KMInteger.cast(num2).length()), - KMInteger.cast(num2).length()); - if (scratchPad[buf] < 0 || scratchPad[(short) (buf + 8)] < 0) - return KMType.INVALID_VALUE; - if (Util.arrayCompare(scratchPad, buf, scratchPad, (short) (buf + 8), - (short) 8) < 1) - return KMType.INVALID_VALUE; - subtract(scratchPad, buf, (short) (buf + 8), (short) (buf + 16)); - return KMInteger.uint_64(scratchPad, (short) (buf + 16)); - }*/ - public static void add(byte[] buf, short op1, short op2, short result) { byte index = 7; byte carry = 0; diff --git a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMAttestationCertImpl.java b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMAttestationCertImpl.java index 5be20599..18e67e72 100644 --- a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMAttestationCertImpl.java +++ b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMAttestationCertImpl.java @@ -121,7 +121,6 @@ public static KMAttestationCert instance(boolean rsaCert) { } private static void init() { - // if (repo == null) repo = KMRepository.instance(); stack = null; stackPtr = 0; certStart = 0; @@ -277,7 +276,6 @@ private static void pushTbsCert(boolean rsaCert) { pushBytes(X509Subject, (short) 0, (short) X509Subject.length); pushValidity(); // issuer - der encoded - // pushBytes(repo.getCertDataBuffer(), repo.getIssuer(), repo.getIssuerLen()); pushBytes( KMByteBlob.cast(issuer).getBuffer(), KMByteBlob.cast(issuer).getStartOff(), @@ -298,23 +296,6 @@ private static void pushTbsCert(boolean rsaCert) { private static void pushExtensions() { short last = stackPtr; - // byte keyusage = 0; - // byte unusedBits = 8; - /* - if (KMEnumArrayTag.contains(KMType.PURPOSE, KMType.SIGN, hwParams)) { - keyusage = (byte) (keyusage | keyUsageSign); - unusedBits = 7; - } - if (KMEnumArrayTag.contains(KMType.PURPOSE, KMType.WRAP_KEY, hwParams)) { - keyusage = (byte) (keyusage | keyUsageKeyEncipher); - unusedBits = 5; - } - if (KMEnumArrayTag.contains(KMType.PURPOSE, KMType.DECRYPT, hwParams)) { - keyusage = (byte) (keyusage | keyUsageDataEncipher); - unusedBits = 4; - } - - */ if (keyUsage != 0) pushKeyUsage(keyUsage, unusedBits); pushKeyDescription(); pushSequenceHeader((short) (last - stackPtr)); @@ -559,7 +540,6 @@ private static void pushTag(short tag) { private static void pushRoT() { short last = stackPtr; // verified boot hash - // pushOctetString(repo.verifiedBootHash, (short) 0, (short) repo.verifiedBootHash.length); pushOctetString( KMByteBlob.cast(verifiedHash).getBuffer(), KMByteBlob.cast(verifiedHash).getStartOff(), diff --git a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMCipher.java b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMCipher.java index 017a8398..3e67ed5e 100644 --- a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMCipher.java +++ b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMCipher.java @@ -16,30 +16,6 @@ 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; - public static final byte PAD_PKCS1_OAEP_SHA256 = 14; - public static final short PAD_PKCS1_OAEP_SHA384 = 15; - public static final short PAD_PKCS1_OAEP_SHA512 = 16; - public static final short PAD_NOPAD = 1; - public static final short PAD_PKCS1_PSS = 8; - public static final short PAD_NULL = 0; - public static final short PAD_PKCS7 = 31; // Not supported in javacard - public static final short ALG_DES_CBC_NOPAD = 1; - public static final short ALG_DES_ECB_NOPAD = 5; - public static final short ALG_AES_BLOCK_128_CBC_NOPAD= 13; - public static final short ALG_AES_BLOCK_128_ECB_NOPAD = 14; - public static final short ALG_AES_GCM = -13; - public static final short MODE_ENCRYPT = 2; - public static final short MODE_DECRYPT = 1; - public static final short PAD_PKCS1 = 7; - 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); diff --git a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMCipherImpl.java b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMCipherImpl.java index 7a1df761..bc07be8d 100644 --- a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMCipherImpl.java +++ b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMCipherImpl.java @@ -30,7 +30,6 @@ public class KMCipherImpl extends KMCipher{ private short cipherAlg; private short padding; private short mode; - private boolean verificationFlag; private short blockMode; KMCipherImpl(Cipher c){ cipher = c; @@ -59,7 +58,6 @@ public short doFinal(byte[] buffer, short startOff, short length, byte[] scratch return (short)sunCipher.doFinal(buffer,startOff,length,scratchPad,i); } catch (AEADBadTagException e) { e.printStackTrace(); - verificationFlag = false; KMException.throwIt(KMError.VERIFICATION_FAILED); } catch (ShortBufferException e) { e.printStackTrace(); diff --git a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMJCardSimulator.java b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMJCardSimulator.java index 6b0596ae..664ade77 100644 --- a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMJCardSimulator.java +++ b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMJCardSimulator.java @@ -72,6 +72,7 @@ public class KMJCardSimulator implements KMSEProvider { public static final short ENTROPY_POOL_SIZE = 16; // simulator does not support 256 bit aes keys 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; @@ -155,7 +156,6 @@ public AESKey createAESKey(short keysize) { return createAESKey(rndNum, (short)0, (short)rndNum.length); } - // @Override public AESKey createAESKey(byte[] buf, short startOff, short length) { AESKey key = null; short keysize = (short)(length * 8); @@ -166,9 +166,6 @@ public AESKey createAESKey(byte[] buf, short startOff, short length) { key = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES, KeyBuilder.LENGTH_AES_256, false); key.setKey(buf, (short) startOff); } - // byte[] buffer = new byte[length]; - // Util.arrayCopyNonAtomic(buf, startOff, buffer, (short)0,length); - // print("AES Key", buffer); return key; } @@ -221,13 +218,27 @@ public void createAsymmetricKey(byte alg, byte[] privKeyBuf, short privKeyStart, byte[] pubModBuf, short pubModStart, short pubModLength, short[] lengths){ switch (alg){ case KMType.RSA: + if (RSA_KEY_SIZE != privKeyLength || RSA_KEY_SIZE != pubModLength) { + CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); + } KeyPair rsaKey = createRsaKeyPair(); RSAPrivateKey privKey = (RSAPrivateKey) rsaKey.getPrivate(); - lengths[0] = privKey.getExponent(privKeyBuf,privKeyStart); - lengths[1] = privKey.getModulus(pubModBuf,pubModStart); - if(lengths[0] > privKeyLength || lengths[1] > pubModLength){ + //Copy exponent. + byte[] exp = new byte[RSA_KEY_SIZE]; + lengths[0] = privKey.getExponent(exp, (short)0); + if (lengths[0] > privKeyLength) CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); - } + Util.arrayFillNonAtomic(privKeyBuf, privKeyStart, privKeyLength, (byte)0); + Util.arrayCopyNonAtomic(exp, (short)0, + privKeyBuf, (short)(privKeyStart + privKeyLength - lengths[0]), lengths[0]); + //Copy modulus + byte[] mod = new byte[RSA_KEY_SIZE]; + lengths[1] = privKey.getModulus(mod, (short)0); + if (lengths[1] > pubModLength) + CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); + Util.arrayFillNonAtomic(pubModBuf, pubModStart, pubModLength, (byte)0); + Util.arrayCopyNonAtomic(mod, (short)0, + pubModBuf, (short)(pubModStart + pubModLength - lengths[1]), lengths[1]); break; case KMType.EC: KeyPair ecKey = createECKeyPair(); @@ -312,20 +323,6 @@ public short aesGCMEncrypt( if(keyLen != 32 && keyLen != 16){ CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); } - /*byte[] keyMaterial = new byte[key]; - short keySize = 16; - if(key.getSize() == 128){ - keyMaterial = new byte[16]; - }else if(key.getSize() == 256){ - keyMaterial = new byte[32]; - keySize = 32; - } - key.getKey(keyMaterial,(short)0); - - */ - - //print("KeyMaterial Enc", keyMaterial); - //print("Authdata Enc", authData, authDataStart, authDataLen); java.security.Key aesKey = new SecretKeySpec(keyBuf,keyStart,keyLen, "AES"); // Create the cipher javax.crypto.Cipher cipher = null; @@ -361,7 +358,6 @@ public short aesGCMEncrypt( // Create auth data byte[] aad = new byte[authDataLen]; Util.arrayCopyNonAtomic(authData,authDataStart,aad,(short)0,authDataLen); - // print("AAD", aad); cipher.updateAAD(aad); // Encrypt secret short len = 0; @@ -402,73 +398,67 @@ public boolean aesGCMDecrypt( short authDataLen, byte[] authTag, short authTagStart, - short authTagLen) { - //Create the sun jce compliant aes key - if(keyLen != 32 && keyLen != 16){ + short authTagLen) { + // Create the sun jce compliant aes key + if (keyLen != 32 && keyLen != 16) { CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); } - /*byte[] keyMaterial = new byte[16]; - short keySize = 16; - if(key.getSize() == 128){ - keyMaterial = new byte[16]; - }else if(key.getSize() == 256){ - keyMaterial = new byte[32]; - keySize = 32; - } - key.getKey(keyMaterial,(short)0); - - */ - //print("KeyMaterial Dec", keyMaterial); - //print("Authdata Dec", authData, authDataStart, authDataLen); - java.security.Key aesKey = new SecretKeySpec(keyBuf,keyStart,keyLen, "AES"); + java.security.Key aesKey = new SecretKeySpec(keyBuf, keyStart, keyLen, + "AES"); // Create the cipher - javax.crypto.Cipher cipher = null; - try { - cipher = javax.crypto.Cipher.getInstance("AES/GCM/NoPadding", "SunJCE"); - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); - } catch (NoSuchProviderException e) { - e.printStackTrace(); - CryptoException.throwIt(CryptoException.INVALID_INIT); - } catch (NoSuchPaddingException e) { - e.printStackTrace(); - CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); - } - // Copy nonce - if(nonceLen != AES_GCM_NONCE_LENGTH){ - CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); - } - byte[] iv = new byte[AES_GCM_NONCE_LENGTH]; - Util.arrayCopyNonAtomic(nonce,nonceStart,iv,(short)0,AES_GCM_NONCE_LENGTH); - // Init Cipher - GCMParameterSpec spec = new GCMParameterSpec(authTagLen * 8, nonce,nonceStart,AES_GCM_NONCE_LENGTH); - try { - cipher.init(javax.crypto.Cipher.DECRYPT_MODE, aesKey, spec); - } catch (InvalidKeyException e) { - e.printStackTrace(); - CryptoException.throwIt(CryptoException.INVALID_INIT); - } catch (InvalidAlgorithmParameterException e) { - e.printStackTrace(); - CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); - } - // Create auth data - byte[] aad = new byte[authDataLen]; - Util.arrayCopyNonAtomic(authData,authDataStart,aad,(short)0,authDataLen); - cipher.updateAAD(aad); - // Append the auth tag at the end of data - byte[] inputBuf = new byte[(short)(encSecretLen + authTagLen)]; - Util.arrayCopyNonAtomic(encSecret,encSecretStart,inputBuf,(short)0,encSecretLen); - Util.arrayCopyNonAtomic(authTag,authTagStart,inputBuf,encSecretLen,authTagLen); - // Decrypt + javax.crypto.Cipher cipher = null; + try { + cipher = javax.crypto.Cipher.getInstance("AES/GCM/NoPadding", "SunJCE"); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); + } catch (NoSuchProviderException e) { + e.printStackTrace(); + CryptoException.throwIt(CryptoException.INVALID_INIT); + } catch (NoSuchPaddingException e) { + e.printStackTrace(); + CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); + } + // Copy nonce + if (nonceLen != AES_GCM_NONCE_LENGTH) { + CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); + } + byte[] iv = new byte[AES_GCM_NONCE_LENGTH]; + Util.arrayCopyNonAtomic(nonce, nonceStart, iv, (short) 0, + AES_GCM_NONCE_LENGTH); + // Init Cipher + GCMParameterSpec spec = new GCMParameterSpec(authTagLen * 8, nonce, + nonceStart, AES_GCM_NONCE_LENGTH); + try { + cipher.init(javax.crypto.Cipher.DECRYPT_MODE, aesKey, spec); + } catch (InvalidKeyException e) { + e.printStackTrace(); + CryptoException.throwIt(CryptoException.INVALID_INIT); + } catch (InvalidAlgorithmParameterException e) { + e.printStackTrace(); + CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); + } + // Create auth data + byte[] aad = new byte[authDataLen]; + Util.arrayCopyNonAtomic(authData, authDataStart, aad, (short) 0, + authDataLen); + cipher.updateAAD(aad); + // Append the auth tag at the end of data + byte[] inputBuf = new byte[(short) (encSecretLen + authTagLen)]; + Util.arrayCopyNonAtomic(encSecret, encSecretStart, inputBuf, (short) 0, + encSecretLen); + Util.arrayCopyNonAtomic(authTag, authTagStart, inputBuf, encSecretLen, + authTagLen); + // Decrypt short len = 0; - byte[] outputBuf = new byte[cipher.getOutputSize((short)inputBuf.length)]; + byte[] outputBuf = new byte[cipher.getOutputSize((short) inputBuf.length)]; try { - len = (short)(cipher.doFinal(inputBuf,(short)0,(short)inputBuf.length,outputBuf,(short)0)); - }catch(AEADBadTagException e){ + len = (short) (cipher.doFinal(inputBuf, (short) 0, + (short) inputBuf.length, outputBuf, (short) 0)); + } catch (AEADBadTagException e) { e.printStackTrace(); return false; - }catch (ShortBufferException e) { + } catch (ShortBufferException e) { e.printStackTrace(); CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); } catch (IllegalBlockSizeException e) { @@ -478,8 +468,8 @@ public boolean aesGCMDecrypt( e.printStackTrace(); CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); } - //Copy the decrypted data - Util.arrayCopyNonAtomic(outputBuf, (short)0,secret,secretStart,len); + // Copy the decrypted data + Util.arrayCopyNonAtomic(outputBuf, (short) 0, secret, secretStart, len); return true; } @@ -641,50 +631,7 @@ public KMOperation initAsymmetricOperation(byte purpose, byte alg, byte padding, CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); return null; } -/* - @Override - public short updateOperation(short opHandle, byte[] inputDataBuf, short inputDataStart, short inputDataLength, byte[] outputDataBuf, short outputDataStart) { - Object op = findOperation(opHandle); - if(op instanceof Signature ){ - ((Signature)op).update(inputDataBuf,inputDataStart,inputDataLength); - return 0; - }else{ - return ((KMCipher)op).update(inputDataBuf,inputDataStart,inputDataLength,outputDataBuf,outputDataStart); - } - } - - @Override - public short finishOperation(short opHandle, byte[] inputDataBuf, short inputDataStart, short inputDataLength, byte[] outputDataBuf, short outputDataStart) { - Object op = findOperation(opHandle); - short ret = 0; - if(op instanceof Signature ){ - ret = ((Signature)op).sign(inputDataBuf,inputDataStart,inputDataLength,outputDataBuf,outputDataStart); - }else{ - ret = ((KMCipher)op).doFinal(inputDataBuf,inputDataStart,inputDataLength,outputDataBuf,outputDataStart); - } - removeOperation(opHandle); - return ret; - } - - @Override - public void abortOperation(short opHandle) { - removeOperation(opHandle); - } - @Override - public void updateAAD(short opHandle, byte[] dataBuf, short dataStart, short dataLength) { - KMCipher aesGcm = (KMCipher) findOperation(opHandle); - aesGcm.updateAAD(dataBuf, dataStart, dataLength); - } - - @Override - public void getAESGCMOutputSize(short opHandle, short dataSize, short macLength) { - KMCipher aesGcm = (KMCipher) findOperation(opHandle); - aesGcm.getAesGcmOutputSize(dataSize, macLength); - } - */ - - public KMCipher createRsaDecipher(short padding, short digest, byte[] secret, short secretStart, short secretLength, byte[] modBuffer, short modOff, short modLength) { byte cipherAlg = mapCipherAlg(KMType.RSA, (byte)padding, (byte)0); @@ -783,12 +730,7 @@ public Signature createRsaSigner(short digest, short padding, byte[] secret, (padding == KMType.RSA_PKCS1_1_5_SIGN && digest == KMType.DIGEST_NONE)) { return createNoDigestSigner(padding,secret, secretStart, secretLength, modBuffer, modOff, modLength); - }/* - else if (padding == KMCipher.PAD_PKCS1_PSS) alg = Signature.ALG_RSA_SHA_256_PKCS1_PSS; - else if (padding == KMCipher.PAD_PKCS1) { - alg = Signature.ALG_RSA_SHA_256_PKCS1; - }else CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); - */ + } Signature rsaSigner = Signature.getInstance((byte)alg, false); RSAPrivateKey key = (RSAPrivateKey) KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_PRIVATE, KeyBuilder.LENGTH_RSA_2048, false); key.setExponent(secret,secretStart,secretLength); @@ -1038,8 +980,6 @@ public KMCipher createAesGcmCipher(short mode, short tagLen, byte[] secret, shor //Create the sun jce compliant aes key byte[] keyMaterial = new byte[secretLength]; Util.arrayCopyNonAtomic(secret,secretStart,keyMaterial,(short)0,secretLength); - //print("KeyMaterial Enc", keyMaterial); - //print("Authdata Enc", authData, authDataStart, authDataLen); java.security.Key aesKey = new SecretKeySpec(keyMaterial,(short)0,keyMaterial.length, "AES"); // Create the cipher javax.crypto.Cipher cipher = null; @@ -1218,7 +1158,6 @@ public Signature createEcVerifier(short digest, byte[] pubKey, short pubKeyStart @Override public KMAttestationCert getAttestationCert(boolean rsaCert) { - //certBuilder.reset(); return KMAttestationCertImpl.instance(rsaCert); } diff --git a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMUtils.java b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMUtils.java index 7b4352f8..65e83415 100644 --- a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMUtils.java +++ b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMUtils.java @@ -347,29 +347,6 @@ public static void shiftRight(byte[] buf, short start) { } } - - // num1 must be greater then or equal to num2 and both must be positive - /*private short subtractIntegers(short num1, short num2) { - short buf = - repository.alloc((short)24); byte[] scratchPad = repository.getHeap(); - Util.arrayFillNonAtomic(scratchPad, buf, (short) 24, (byte) 0); - Util.arrayCopyNonAtomic(KMInteger.cast(num1).getBuffer(), - KMInteger.cast(num1).getStartOff(), scratchPad, - (short) (buf + 8 - KMInteger.cast(num1).length()), - KMInteger.cast(num1).length()); - Util.arrayCopyNonAtomic(KMInteger.cast(num2).getBuffer(), - KMInteger.cast(num2).getStartOff(), scratchPad, - (short) (buf + 16 - KMInteger.cast(num2).length()), - KMInteger.cast(num2).length()); - if (scratchPad[buf] < 0 || scratchPad[(short) (buf + 8)] < 0) - return KMType.INVALID_VALUE; - if (Util.arrayCompare(scratchPad, buf, scratchPad, (short) (buf + 8), - (short) 8) < 1) - return KMType.INVALID_VALUE; - subtract(scratchPad, buf, (short) (buf + 8), (short) (buf + 16)); - return KMInteger.uint_64(scratchPad, (short) (buf + 16)); - }*/ - public static void add(byte[] buf, short op1, short op2, short result) { byte index = 7; byte carry = 0; diff --git a/Applet/JCardSimProvider/test/com/android/javacard/test/KMFunctionalTest.java b/Applet/JCardSimProvider/test/com/android/javacard/test/KMFunctionalTest.java index 74892031..a6308513 100644 --- a/Applet/JCardSimProvider/test/com/android/javacard/test/KMFunctionalTest.java +++ b/Applet/JCardSimProvider/test/com/android/javacard/test/KMFunctionalTest.java @@ -17,8 +17,6 @@ package com.android.javacard.test; import com.android.javacard.keymaster.KMArray; -import com.android.javacard.keymaster.KMAttestationCert; -import com.android.javacard.keymaster.KMAttestationCertImpl; import com.android.javacard.keymaster.KMBoolTag; import com.android.javacard.keymaster.KMByteBlob; import com.android.javacard.keymaster.KMByteTag; @@ -43,13 +41,15 @@ import com.android.javacard.keymaster.KMVerificationToken; import com.licel.jcardsim.smartcardio.CardSimulator; import com.licel.jcardsim.utils.AIDUtil; + import javacard.framework.AID; import javacard.framework.Util; - -import java.security.spec.PKCS8EncodedKeySpec; +import java.util.Arrays; +import java.util.Random; import javax.smartcardio.CommandAPDU; import javax.smartcardio.ResponseAPDU; + import org.junit.Assert; import org.junit.Test; @@ -2027,6 +2027,168 @@ public void testSignWithRsaNonePkcs1(){ cleanUp(); } + public byte[] EncryptMessage(byte[] input, short params, byte[] keyBlob) { + short ret = begin(KMType.ENCRYPT, + KMByteBlob.instance(keyBlob, (short) 0, (short) keyBlob.length), + KMKeyParameters.instance(params), (short) 0); + // Get the operation handle. + short opHandle = KMArray.cast(ret).get((short) 2); + byte[] opHandleBuf = new byte[KMRepository.OPERATION_HANDLE_SIZE]; + KMInteger.cast(opHandle).getValue(opHandleBuf, (short) 0, + (short) opHandleBuf.length); + opHandle = KMInteger.uint_64(opHandleBuf, (short) 0); + + ret = finish(opHandle, + KMByteBlob.instance(input, (short) 0, (short) input.length), null, + (short) 0, (short) 0, (short) 0, KMError.OK); + short dataPtr = KMArray.cast(ret).get((short) 2); + byte[] output = new byte[KMByteBlob.cast(dataPtr).length()]; + if (KMByteBlob.cast(dataPtr).length() > 0) { + Util.arrayCopyNonAtomic(KMByteBlob.cast(dataPtr).getBuffer(), KMByteBlob + .cast(dataPtr).getStartOff(), output, (short) 0, + KMByteBlob.cast(dataPtr).length()); + } + return output; + } + + public byte[] DecryptMessage(byte[] input, short params, byte[] keyBlob) { + short ret = begin(KMType.DECRYPT, + KMByteBlob.instance(keyBlob, (short) 0, (short) keyBlob.length), + KMKeyParameters.instance(params), (short) 0); + // Get the operation handle. + short opHandle = KMArray.cast(ret).get((short) 2); + byte[] opHandleBuf = new byte[KMRepository.OPERATION_HANDLE_SIZE]; + KMInteger.cast(opHandle).getValue(opHandleBuf, (short) 0, + (short) opHandleBuf.length); + opHandle = KMInteger.uint_64(opHandleBuf, (short) 0); + + ret = finish(opHandle, + KMByteBlob.instance(input, (short) 0, (short) input.length), null, + (short) 0, (short) 0, (short) 0, KMError.OK); + short dataPtr = KMArray.cast(ret).get((short) 2); + byte[] output = new byte[KMByteBlob.cast(dataPtr).length()]; + if (KMByteBlob.cast(dataPtr).length() > 0) { + Util.arrayCopyNonAtomic(KMByteBlob.cast(dataPtr).getBuffer(), KMByteBlob + .cast(dataPtr).getStartOff(), output, (short) 0, + KMByteBlob.cast(dataPtr).length()); + } + return output; + } + + public short generateRandom(short upperBound) { + Random rand = new Random(); + short int_random = (short) rand.nextInt(upperBound); + return int_random; + } + + @Test + public void testDesEcbPkcs7PaddingCorrupted() { + init(); + short desKey = generateAesDesKey(KMType.DES, (short) 168, null, null, false); + short desKeyPtr = KMArray.cast(desKey).get((short) 1); + byte[] keyBlob = new byte[KMByteBlob.cast(desKeyPtr).length()]; + Util.arrayCopyNonAtomic(KMByteBlob.cast(desKeyPtr).getBuffer(), KMByteBlob + .cast(desKeyPtr).getStartOff(), keyBlob, (short) 0, + (short) keyBlob.length); + + byte[] message = { + 0x61 }; + short desPkcs7Params = getAesDesParams(KMType.DES, KMType.ECB, + KMType.PKCS7, null); + byte[] cipherText1 = EncryptMessage(message, desPkcs7Params, keyBlob); + Assert.assertEquals(8, cipherText1.length); + Assert.assertFalse(Arrays.equals(message, cipherText1)); + + // Corrupt the cipher text. + ++cipherText1[(cipherText1.length / 2)]; + + // Decrypt operation + // Begin + desPkcs7Params = getAesDesParams(KMType.DES, KMType.ECB, KMType.PKCS7, null); + + short ret = begin(KMType.DECRYPT, + KMByteBlob.instance(keyBlob, (short) 0, (short) keyBlob.length), + KMKeyParameters.instance(desPkcs7Params), (short) 0); + // Get the operation handle. + short opHandle = KMArray.cast(ret).get((short) 2); + byte[] opHandleBuf = new byte[KMRepository.OPERATION_HANDLE_SIZE]; + KMInteger.cast(opHandle).getValue(opHandleBuf, (short) 0, + (short) opHandleBuf.length); + opHandle = KMInteger.uint_64(opHandleBuf, (short) 0); + + // Finish + short dataPtr = KMByteBlob.instance(cipherText1, (short) 0, + (short) cipherText1.length); + opHandle = KMInteger.uint_64(opHandleBuf, (short) 0); + ret = finish(opHandle, dataPtr, null, (short) 0, (short) 0, (short) 0, + KMError.INVALID_ARGUMENT); + cleanUp(); + } + + @Test + public void testVtsRsaPkcs1Success() { + init(); + byte[] message = { + 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, + 0x21 }; // "Hello World!"; + for (int i = 0; i < 250; i++) { + short key = generateRsaKey(null, null); + short rsaKeyPtr = KMArray.cast(key).get((short) 1); + byte[] keyBlob = new byte[KMByteBlob.cast(rsaKeyPtr).length()]; + Util.arrayCopyNonAtomic(KMByteBlob.cast(rsaKeyPtr).getBuffer(), + KMByteBlob.cast(rsaKeyPtr).getStartOff(), keyBlob, (short) 0, + (short) keyBlob.length); + short pkcs1Params = getRsaParams(KMType.DIGEST_NONE, + KMType.RSA_PKCS1_1_5_ENCRYPT); + + byte[] cipherText1 = EncryptMessage(message, pkcs1Params, keyBlob); + Assert.assertEquals((2048 / 8), cipherText1.length); + + pkcs1Params = getRsaParams(KMType.DIGEST_NONE, + KMType.RSA_PKCS1_1_5_ENCRYPT); + byte[] cipherText2 = EncryptMessage(message, pkcs1Params, keyBlob); + Assert.assertEquals((2048 / 8), cipherText2.length); + + // PKCS1 v1.5 randomizes padding so every result should be different. + Assert.assertFalse(Arrays.equals(cipherText1, cipherText2)); + + pkcs1Params = getRsaParams(KMType.DIGEST_NONE, + KMType.RSA_PKCS1_1_5_ENCRYPT); + byte[] plainText = DecryptMessage(cipherText1, pkcs1Params, keyBlob); + Assert.assertTrue(Arrays.equals(message, plainText)); + + // Decrypting corrupted ciphertext should fail. + short offset_to_corrupt = generateRandom((short) cipherText1.length); + + byte corrupt_byte; + do { + corrupt_byte = (byte) generateRandom((short) 256); + } while (corrupt_byte == cipherText1[offset_to_corrupt]); + cipherText1[offset_to_corrupt] = corrupt_byte; + + pkcs1Params = getRsaParams(KMType.DIGEST_NONE, + KMType.RSA_PKCS1_1_5_ENCRYPT); + // Do Begin operation. + short ret = begin(KMType.DECRYPT, + KMByteBlob.instance(keyBlob, (short) 0, (short) keyBlob.length), + KMKeyParameters.instance(pkcs1Params), (short) 0); + + // Get the operation handle. + short opHandle = KMArray.cast(ret).get((short) 2); + byte[] opHandleBuf = new byte[KMRepository.OPERATION_HANDLE_SIZE]; + KMInteger.cast(opHandle).getValue(opHandleBuf, (short) 0, + (short) opHandleBuf.length); + opHandle = KMInteger.uint_64(opHandleBuf, (short) 0); + + short dataPtr = KMByteBlob.instance(cipherText1, (short) 0, + (short) cipherText1.length); + // Finish should return UNKNOWN_ERROR. + ret = finish(opHandle, dataPtr, null, (short) 0, (short) 0, (short) 0, + KMError.UNKNOWN_ERROR); + } + cleanUp(); + } + @Test public void testSignVerifyWithHmacSHA256WithUpdate(){ init(); @@ -2560,9 +2722,9 @@ public short processMessage( opHandle = KMInteger.uint_64(opHandleBuf, (short) 0); if (keyPurpose == KMType.VERIFY) { - ret = finish(opHandle, dataPtr, signature, (short) 0, (short) 0, (short) 0); + ret = finish(opHandle, dataPtr, signature, (short) 0, (short) 0, (short) 0, KMError.OK); } else { - ret = finish(opHandle, dataPtr, null, (short) 0, (short) 0, (short) 0); + ret = finish(opHandle, dataPtr, null, (short) 0, (short) 0, (short) 0, KMError.OK); } if(len >0){ dataPtr = KMArray.cast(ret).get((short)2); @@ -2610,7 +2772,34 @@ public short begin(byte keyPurpose, short keyBlob, short keyParmas, short hwToke } } - public short finish(short operationHandle, short data, byte[] signature, short inParams, short hwToken, short verToken) { + public short translateExtendedErrorCodes(short err) { + switch (err) { + case KMError.SW_CONDITIONS_NOT_SATISFIED: + case KMError.UNSUPPORTED_CLA: + case KMError.INVALID_P1P2: + case KMError.INVALID_DATA: + case KMError.CRYPTO_ILLEGAL_USE: + case KMError.CRYPTO_ILLEGAL_VALUE: + case KMError.CRYPTO_INVALID_INIT: + case KMError.CRYPTO_UNINITIALIZED_KEY: + case KMError.GENERIC_UNKNOWN_ERROR: + err = KMError.UNKNOWN_ERROR; + break; + case KMError.CRYPTO_NO_SUCH_ALGORITHM: + err = KMError.UNSUPPORTED_ALGORITHM; + break; + case KMError.UNSUPPORTED_INSTRUCTION: + case KMError.CMD_NOT_ALLOWED: + case KMError.SW_WRONG_LENGTH: + err = KMError.UNIMPLEMENTED; + break; + default: + break; + } + return err; + } + + public short finish(short operationHandle, short data, byte[] signature, short inParams, short hwToken, short verToken, short expectedErr) { if(hwToken == 0) { hwToken = KMHardwareAuthToken.instance(); } @@ -2637,16 +2826,27 @@ public short finish(short operationHandle, short data, byte[] signature, short i CommandAPDU apdu = encodeApdu((byte)INS_FINISH_OPERATION_CMD, arrPtr); // print(commandAPDU.getBytes()); ResponseAPDU response = simulator.transmitCommand(apdu); - short ret = KMArray.instance((short) 3); - short outParams = KMKeyParameters.exp(); - KMArray.cast(ret).add((short)0, KMInteger.exp()); - KMArray.cast(ret).add((short)1, outParams); - KMArray.cast(ret).add((short)2, KMByteBlob.exp()); byte[] respBuf = response.getBytes(); short len = (short) respBuf.length; + short ret; + short error; + if (expectedErr == KMError.OK) { + ret = KMArray.instance((short) 3); + short outParams = KMKeyParameters.exp(); + KMArray.cast(ret).add((short)0, KMInteger.exp()); + KMArray.cast(ret).add((short)1, outParams); + KMArray.cast(ret).add((short)2, KMByteBlob.exp()); + } else { + ret = KMInteger.exp(); + } ret = decoder.decode(ret, respBuf, (short) 0, len); - short error = KMInteger.cast(KMArray.cast(ret).get((short)0)).getShort(); - Assert.assertEquals(error, KMError.OK); + if (expectedErr == KMError.OK) { + error = KMInteger.cast(KMArray.cast(ret).get((short)0)).getShort(); + } else { + error = KMInteger.cast(ret).getShort(); + error = translateExtendedErrorCodes(error); + } + Assert.assertEquals(error, expectedErr); return ret; } public short update(short operationHandle, short data, short inParams, short hwToken, short verToken) { diff --git a/Applet/src/com/android/javacard/keymaster/KMError.java b/Applet/src/com/android/javacard/keymaster/KMError.java index 8f842236..83eb8c7c 100644 --- a/Applet/src/com/android/javacard/keymaster/KMError.java +++ b/Applet/src/com/android/javacard/keymaster/KMError.java @@ -20,100 +20,100 @@ * positive unlike negative values in keymaster hal. */ public class KMError { - public static short OK = 0; - public static short ROOT_OF_TRUST_ALREADY_SET = 1; - public static short UNSUPPORTED_PURPOSE = 2; - public static short INCOMPATIBLE_PURPOSE = 3; - public static short UNSUPPORTED_ALGORITHM = 4; - public static short INCOMPATIBLE_ALGORITHM = 5; - public static short UNSUPPORTED_KEY_SIZE = 6; - public static short UNSUPPORTED_BLOCK_MODE = 7; - public static short INCOMPATIBLE_BLOCK_MODE = 8; - public static short UNSUPPORTED_MAC_LENGTH = 9; - public static short UNSUPPORTED_PADDING_MODE = 10; - public static short INCOMPATIBLE_PADDING_MODE = 11; - public static short UNSUPPORTED_DIGEST = 12; - public static short INCOMPATIBLE_DIGEST = 13; - public static short INVALID_EXPIRATION_TIME = 14; - public static short INVALID_USER_ID = 15; - public static short INVALID_AUTHORIZATION_TIMEOUT = 16; - public static short UNSUPPORTED_KEY_FORMAT = 17; - public static short INCOMPATIBLE_KEY_FORMAT = 18; - public static short UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM = 19; + 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 */ - public static short UNSUPPORTED_KEY_VERIFICATION_ALGORITHM = 20; + public static final short UNSUPPORTED_KEY_VERIFICATION_ALGORITHM = 20; /** For PKCS8 & PKCS12 */ - public static short INVALID_INPUT_LENGTH = 21; + public static final short INVALID_INPUT_LENGTH = 21; - public static short KEY_EXPORT_OPTIONS_INVALID = 22; - public static short DELEGATION_NOT_ALLOWED = 23; - public static short KEY_NOT_YET_VALID = 24; - public static short KEY_EXPIRED = 25; - public static short KEY_USER_NOT_AUTHENTICATED = 26; - public static short OUTPUT_PARAMETER_NULL = 27; - public static short INVALID_OPERATION_HANDLE = 28; - public static short INSUFFICIENT_BUFFER_SPACE = 29; - public static short VERIFICATION_FAILED = 30; - public static short TOO_MANY_OPERATIONS = 31; - public static short UNEXPECTED_NULL_POINTER = 32; - public static short INVALID_KEY_BLOB = 33; - public static short IMPORTED_KEY_NOT_ENCRYPTED = 34; - public static short IMPORTED_KEY_DECRYPTION_FAILED = 35; - public static short IMPORTED_KEY_NOT_SIGNED = 36; - public static short IMPORTED_KEY_VERIFICATION_FAILED = 37; - public static short INVALID_ARGUMENT = 38; - public static short UNSUPPORTED_TAG = 39; - public static short INVALID_TAG = 40; - public static short MEMORY_ALLOCATION_FAILED = 41; - public static short IMPORT_PARAMETER_MISMATCH = 44; - public static short SECURE_HW_ACCESS_DENIED = 45; - public static short OPERATION_CANCELLED = 46; - public static short CONCURRENT_ACCESS_CONFLICT = 47; - public static short SECURE_HW_BUSY = 48; - public static short SECURE_HW_COMMUNICATION_FAILED = 49; - public static short UNSUPPORTED_EC_FIELD = 50; - public static short MISSING_NONCE = 51; - public static short INVALID_NONCE = 52; - public static short MISSING_MAC_LENGTH = 53; - public static short KEY_RATE_LIMIT_EXCEEDED = 54; - public static short CALLER_NONCE_PROHIBITED = 55; - public static short KEY_MAX_OPS_EXCEEDED = 56; - public static short INVALID_MAC_LENGTH = 57; - public static short MISSING_MIN_MAC_LENGTH = 58; - public static short UNSUPPORTED_MIN_MAC_LENGTH = 59; - public static short UNSUPPORTED_KDF = 60; - public static short UNSUPPORTED_EC_CURVE = 61; - public static short KEY_REQUIRES_UPGRADE = 62; - public static short ATTESTATION_CHALLENGE_MISSING = 63; - public static short KEYMASTER_NOT_CONFIGURED = 64; - public static short ATTESTATION_APPLICATION_ID_MISSING = 65; - public static short CANNOT_ATTEST_IDS = 66; - public static short ROLLBACK_RESISTANCE_UNAVAILABLE = 67; - public static short HARDWARE_TYPE_UNAVAILABLE = 68; - public static short PROOF_OF_PRESENCE_REQUIRED = 69; - public static short CONCURRENT_PROOF_OF_PRESENCE_REQUESTED = 70; - public static short NO_USER_CONFIRMATION = 71; - public static short DEVICE_LOCKED = 72; - public static short EARLY_BOOT_ENDED = 73; - public static short UNIMPLEMENTED = 100; - public static short VERSION_MISMATCH = 101; - public static short UNKNOWN_ERROR = 1000; + 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 - public static short SW_CONDITIONS_NOT_SATISFIED = 10001; - public static short UNSUPPORTED_CLA = 10002; - public static short INVALID_P1P2 = 10003; - public static short UNSUPPORTED_INSTRUCTION = 10004; - public static short CMD_NOT_ALLOWED = 10005; - public static short SW_WRONG_LENGTH = 10006; - public static short INVALID_DATA = 10007; + public static final short SW_CONDITIONS_NOT_SATISFIED = 10001; + public static final short UNSUPPORTED_CLA = 10002; + public static final short INVALID_P1P2 = 10003; + public static final short UNSUPPORTED_INSTRUCTION = 10004; + public static final short CMD_NOT_ALLOWED = 10005; + public static final short SW_WRONG_LENGTH = 10006; + public static final short INVALID_DATA = 10007; //Crypto errors - public static short CRYPTO_ILLEGAL_USE = 10008; - public static short CRYPTO_ILLEGAL_VALUE = 10009; - public static short CRYPTO_INVALID_INIT = 10010; - public static short CRYPTO_NO_SUCH_ALGORITHM = 10011; - public static short CRYPTO_UNINITIALIZED_KEY = 10012; + public static final short CRYPTO_ILLEGAL_USE = 10008; + public static final short CRYPTO_ILLEGAL_VALUE = 10009; + public static final short CRYPTO_INVALID_INIT = 10010; + public static final short CRYPTO_NO_SUCH_ALGORITHM = 10011; + public static final short CRYPTO_UNINITIALIZED_KEY = 10012; //Generic Unknown error. - public static short GENERIC_UNKNOWN_ERROR = 10013; + public static final short GENERIC_UNKNOWN_ERROR = 10013; } diff --git a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java index b30e63c2..abf6e670 100644 --- a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java +++ b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java @@ -520,7 +520,6 @@ private void processDeviceLockedCmd(APDU apdu) { data[VERIFICATION_TOKEN] = KMArray.cast(tmpVariables[0]).get((short) 1); validateVerificationToken(data[VERIFICATION_TOKEN], scratchPad); short verTime = KMVerificationToken.cast(data[VERIFICATION_TOKEN]).getTimestamp(); - // short lastDeviceLockedTime = KMInteger.uint_64(repository.deviceLockedTimestamp, (short)0); short lastDeviceLockedTime = repository.getDeviceTimeStamp(); if (KMInteger.compare(verTime, lastDeviceLockedTime) > 0) { Util.arrayFillNonAtomic(scratchPad, (short) 0, (short) 8, (byte) 0); @@ -538,6 +537,11 @@ private void resetData() { data[index] = KMType.INVALID_VALUE; index++; } + index = 0; + while (index < tmpVariables.length) { + tmpVariables[index] = KMType.INVALID_VALUE; + index++; + } } /** Sends a response, may be extended response, as requested by the command. */ public static void sendOutgoing(APDU apdu) { @@ -3001,7 +3005,6 @@ private void importAESKey(byte[] scratchPad) { KMException.throwIt(KMError.IMPORT_PARAMETER_MISMATCH); } } else { - // add the key size to scratch pad // add the key size to scratchPad tmpVariables[5] = KMInteger.uint_16(KMByteBlob.cast(data[SECRET]).length()); tmpVariables[6] = KMIntegerTag.instance(KMType.UINT_TAG, KMType.KEYSIZE, tmpVariables[5]); @@ -3130,26 +3133,20 @@ private void processSetBootParamsCmd(APDU apdu) { receiveIncoming(apdu); byte[] scratchPad = apdu.getBuffer(); // Argument 1 OS Version - // short osVersionExp = KMIntegerTag.exp(KMType.UINT_TAG); tmpVariables[0] = KMInteger.exp(); // Argument 2 OS Patch level - // short osPatchExp = KMIntegerTag.exp(KMType.UINT_TAG); tmpVariables[1] = KMInteger.exp(); // Argument 3 Vendor Patch level tmpVariables[2] = KMInteger.exp(); // Argument 4 Boot Patch level tmpVariables[3] = KMInteger.exp(); // Argument 5 Verified Boot Key - // short bootKeyExp = KMByteBlob.exp(); tmpVariables[4] = KMByteBlob.exp(); // Argument 6 Verified Boot Hash - // short bootHashExp = KMByteBlob.exp(); tmpVariables[5] = KMByteBlob.exp(); // Argument 7 Verified Boot State - // short bootStateExp = KMEnum.instance(KMType.VERIFIED_BOOT_STATE); tmpVariables[6] = KMEnum.instance(KMType.VERIFIED_BOOT_STATE); // Argument 8 Device Locked - // short deviceLockedExp = KMEnum.instance(KMType.DEVICE_LOCKED); tmpVariables[7] = KMEnum.instance(KMType.DEVICE_LOCKED); // Array of expected arguments short argsProto = KMArray.instance((short) 8); @@ -3166,21 +3163,13 @@ private void processSetBootParamsCmd(APDU apdu) { //reclaim memory repository.reclaimMemory(bufferLength); - // short osVersionTagPtr = KMArray.cast(args).get((short) 0); tmpVariables[0] = KMArray.cast(args).get((short) 0); - // short osPatchTagPtr = KMArray.cast(args).get((short) 1); tmpVariables[1] = KMArray.cast(args).get((short) 1); - // short vendorPatchTagPtr = KMArray.cast(args).get((short) 2); tmpVariables[2] = KMArray.cast(args).get((short) 2); - // short BootPatchTagPtr = KMArray.cast(args).get((short) 3); tmpVariables[3] = KMArray.cast(args).get((short) 3); - // short verifiedBootKeyPtr = KMArray.cast(args).get((short) 4); tmpVariables[4] = KMArray.cast(args).get((short) 4); - // short verifiedBootHashPtr = KMArray.cast(args).get((short) 5); tmpVariables[5] = KMArray.cast(args).get((short) 5); - // short verifiedBootStatePtr = KMArray.cast(args).get((short) 6); tmpVariables[6] = KMArray.cast(args).get((short) 6); - // short deviceLockedPtr = KMArray.cast(args).get((short) 7); tmpVariables[7] = KMArray.cast(args).get((short) 7); if (KMByteBlob.cast(tmpVariables[4]).length() > KMRepository.BOOT_KEY_MAX_SIZE) { KMException.throwIt(KMError.INVALID_ARGUMENT);