diff --git a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAndroidSEProvider.java b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAndroidSEProvider.java index 78b90b57..ac4ae426 100644 --- a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAndroidSEProvider.java +++ b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAndroidSEProvider.java @@ -40,6 +40,8 @@ import com.android.javacard.keymaster.KMAESKey; import com.android.javacard.keymaster.KMAttestationKey; import com.android.javacard.keymaster.KMECPrivateKey; +import com.android.javacard.keymaster.KMError; +import com.android.javacard.keymaster.KMException; import com.android.javacard.keymaster.KMHmacKey; import com.android.javacard.keymaster.KMMasterKey; import com.android.javacard.keymaster.KMPreSharedKey; @@ -1018,51 +1020,6 @@ public Signature createRsaSigner(short digest, short padding, byte[] secret, return rsaSigner; } - public Signature createRsaVerifier(short digest, short padding, - byte[] modBuffer, short modOff, short modLength) { - try { - byte alg = mapSignature256Alg(KMType.RSA, (byte) padding, (byte) digest); - if (digest == KMType.DIGEST_NONE || padding == KMType.PADDING_NONE) - CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); - - Signature rsaVerifier = getSignatureInstanceFromPool(alg); - RSAPublicKey key = (RSAPublicKey) rsaKeyPair.getPublic(); - // setExponent - Util.setShort(tmpArray, (short) 0, (short) 0x0001); - Util.setShort(tmpArray, (short) 2, (short) 0x0001); - key.setExponent(tmpArray, (short) 0, (short) 4); - key.setModulus(modBuffer, modOff, modLength); - rsaVerifier.init(key, Signature.MODE_VERIFY); - return rsaVerifier; - } finally { - clean(); - } - } - - public Cipher createRsaCipher(short padding, short digest, byte[] modBuffer, - short modOff, short modLength) { - try { - byte cipherAlg = mapCipherAlg(KMType.RSA, (byte) padding, (byte) 0, (byte)digest); - // Java Card does not support MGF1-SHA1 and digest as SHA256. - // Both digest should be SHA256 as per Java Card, but as per Keymaster - // MGF should use SHA1 and message digest should be SHA256. - if (cipherAlg == Cipher.ALG_RSA_PKCS1_OAEP) { - KMException.throwIt(KMError.UNIMPLEMENTED); - } - Cipher rsaCipher = getCipherInstanceFromPool(cipherAlg); - RSAPublicKey key = (RSAPublicKey) rsaKeyPair.getPublic(); - // setExponent - Util.setShort(tmpArray, (short) 0, (short) 0x0001); - Util.setShort(tmpArray, (short) 2, (short) 0x0001); - key.setExponent(tmpArray, (short) 0, (short) 4); - key.setModulus(modBuffer, modOff, modLength); - rsaCipher.init(key, Cipher.MODE_ENCRYPT); - return rsaCipher; - } finally { - clean(); - } - } - public Cipher createRsaDecipher(short padding, short digest, byte[] secret, short secretStart, short secretLength, byte[] modBuffer, short modOff, short modLength) { @@ -1086,17 +1043,6 @@ public Signature createEcSigner(short digest, byte[] secret, return ecSigner; } - public Signature createEcVerifier(short digest, byte[] pubKey, - short pubKeyStart, short pubKeyLength) { - byte alg = mapSignature256Alg(KMType.EC, (byte) 0, (byte) digest); - Signature ecVerifier = null; - ECPublicKey key = (ECPublicKey) ecKeyPair.getPublic(); - key.setW(pubKey, pubKeyStart, pubKeyLength); - ecVerifier = getSignatureInstanceFromPool(alg); - ecVerifier.init(key, Signature.MODE_VERIFY); - return ecVerifier; - } - @Override public KMOperation initAsymmetricOperation(byte purpose, byte alg, byte padding, byte digest, byte[] privKeyBuf, short privKeyStart, @@ -1116,28 +1062,6 @@ public KMOperation initAsymmetricOperation(byte purpose, byte alg, opr.setMode(purpose); JCSystem.commitTransaction(); break; - case KMType.VERIFY: - Signature verifier = createRsaVerifier(digest, padding, pubModBuf, - pubModStart, pubModLength); - opr = getOperationInstanceFromPool(); - JCSystem.beginTransaction(); - opr.setSignature(verifier); - opr.setCipherAlgorithm(alg); - opr.setPaddingAlgorithm(padding); - opr.setMode(purpose); - JCSystem.commitTransaction(); - break; - case KMType.ENCRYPT: - Cipher cipher = createRsaCipher(padding, digest, pubModBuf, - pubModStart, pubModLength); - opr = getOperationInstanceFromPool(); - JCSystem.beginTransaction(); - opr.setCipher(cipher); - opr.setCipherAlgorithm(alg); - opr.setPaddingAlgorithm(padding); - opr.setMode(purpose); - JCSystem.commitTransaction(); - break; case KMType.DECRYPT: Cipher decipher = createRsaDecipher(padding, digest, privKeyBuf, privKeyStart, privKeyLength, pubModBuf, pubModStart, pubModLength); @@ -1150,6 +1074,7 @@ public KMOperation initAsymmetricOperation(byte purpose, byte alg, JCSystem.commitTransaction(); break; default: + KMException.throwIt(KMError.UNSUPPORTED_PURPOSE); break; } } else if (alg == KMType.EC) { @@ -1162,13 +1087,8 @@ public KMOperation initAsymmetricOperation(byte purpose, byte alg, opr.setSignature(signer); JCSystem.commitTransaction(); break; - case KMType.VERIFY: - Signature verifier = createEcVerifier(digest, pubModBuf, pubModStart, - pubModLength); - opr = getOperationInstanceFromPool(); - JCSystem.beginTransaction(); - opr.setSignature(verifier); - JCSystem.commitTransaction(); + default: + KMException.throwIt(KMError.UNSUPPORTED_PURPOSE); break; } } else { diff --git a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMEcdsa256NoDigestSignature.java b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMEcdsa256NoDigestSignature.java index 3f11a3b1..51ac435b 100644 --- a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMEcdsa256NoDigestSignature.java +++ b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMEcdsa256NoDigestSignature.java @@ -112,28 +112,14 @@ public short signPreComputedHash(byte[] bytes, short i, short i1, @Override public boolean verify(byte[] bytes, short i, short i1, byte[] bytes1, short i2, short i3) throws CryptoException { - try { - if (i1 > MAX_NO_DIGEST_MSG_LEN) - CryptoException.throwIt(CryptoException.ILLEGAL_USE); - // add zeros to the left - if (i1 < MAX_NO_DIGEST_MSG_LEN) { - Util.arrayFillNonAtomic(KMAndroidSEProvider.getInstance().tmpArray, - (short) 0, (short) MAX_NO_DIGEST_MSG_LEN, (byte) 0); - } - Util.arrayCopyNonAtomic(bytes, i, - KMAndroidSEProvider.getInstance().tmpArray, - (short) (MAX_NO_DIGEST_MSG_LEN - i1), i1); - return inst.verifyPreComputedHash( - KMAndroidSEProvider.getInstance().tmpArray, (short) 0, - (short) MAX_NO_DIGEST_MSG_LEN, bytes1, i2, i3); - } finally { - KMAndroidSEProvider.getInstance().clean(); - } + //Verification is handled inside HAL + return false; } @Override public boolean verifyPreComputedHash(byte[] bytes, short i, short i1, byte[] bytes1, short i2, short i3) throws CryptoException { - return inst.verify(bytes, i, i1, bytes1, i2, i3); + //Verification is handled inside HAL + return false; } } \ No newline at end of file diff --git a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMOperationImpl.java b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMOperationImpl.java index a38ee518..0eb7c4e7 100644 --- a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMOperationImpl.java +++ b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMOperationImpl.java @@ -125,19 +125,6 @@ public short finish(byte[] inputDataBuf, short inputDataStart, if (mode == KMType.DECRYPT) { inputDataLen = (short) (inputDataLen - macLength); } - } else if (cipherAlg == KMType.RSA && padding == KMType.PADDING_NONE && - mode == KMType.ENCRYPT) { - // Length cannot be greater then key size according to Java Card - if (inputDataLen > 256) - KMException.throwIt(KMError.INVALID_INPUT_LENGTH); - // make input equal to 255 bytes - Util.arrayFillNonAtomic(tmpArray, (short) 0, (short) 256, (byte) 0); - Util.arrayCopyNonAtomic(inputDataBuf, inputDataStart, tmpArray, - (short) (256 - inputDataLen), inputDataLen); - inputDataStart = 0; - inputDataLen = 256; - inputDataBuf = tmpArray; - } else if ((cipherAlg == KMType.DES || cipherAlg == KMType.AES) && padding == KMType.PKCS7 && mode == KMType.ENCRYPT) { byte blkSize = 16; diff --git a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMCipherImpl.java b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMCipherImpl.java index bc07be8d..95e5cb83 100644 --- a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMCipherImpl.java +++ b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMCipherImpl.java @@ -81,21 +81,7 @@ public short doFinal(byte[] buffer, short startOff, short length, byte[] scratch CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); } } else{ - if(cipherAlg == KMType.RSA && padding == KMType.PADDING_NONE && mode == KMType.ENCRYPT ){ - // Length cannot be greater then key size according to JcardSim - if(length >= 256) KMException.throwIt(KMError.INVALID_INPUT_LENGTH); - // make input equal to 255 bytes - byte[] tmp = new byte[255]; - Util.arrayFillNonAtomic(tmp,(short)0,(short)255, (byte)0); - Util.arrayCopyNonAtomic( - buffer, - startOff, - tmp, (short)(255 - length),length); - startOff = 0; - length = 255; - buffer = tmp; - - }else if((cipherAlg == KMType.DES || cipherAlg == KMType.AES) && padding ==KMType.PKCS7 && mode == KMType.ENCRYPT){ + if((cipherAlg == KMType.DES || cipherAlg == KMType.AES) && padding ==KMType.PKCS7 && mode == KMType.ENCRYPT){ byte blkSize = 16; byte paddingBytes; short len = length; diff --git a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMEcdsa256NoDigestSignature.java b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMEcdsa256NoDigestSignature.java index 42468363..904353b1 100644 --- a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMEcdsa256NoDigestSignature.java +++ b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMEcdsa256NoDigestSignature.java @@ -173,14 +173,7 @@ public short signPreComputedHash(byte[] bytes, short i, short i1, byte[] bytes1, @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) { - CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); - } + // Public key operations not handled here. return false; } diff --git a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMJCardSimulator.java b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMJCardSimulator.java index 664ade77..0dad8f77 100644 --- a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMJCardSimulator.java +++ b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMJCardSimulator.java @@ -605,17 +605,13 @@ public KMOperation initAsymmetricOperation(byte purpose, byte alg, byte padding, pubModStart, pubModLength); return new KMOperationImpl(signer); - case KMType.VERIFY: - Signature verifier = createRsaVerifier(digest, padding, pubModBuf, pubModStart, pubModLength); - return new KMOperationImpl(verifier); - case KMType.ENCRYPT: - KMCipher cipher = createRsaCipher(padding, digest, pubModBuf, pubModStart, pubModLength); - return new KMOperationImpl(cipher); case KMType.DECRYPT: KMCipher decipher = createRsaDecipher( padding, digest, privKeyBuf, privKeyStart, privKeyLength, pubModBuf, pubModStart, pubModLength); return new KMOperationImpl(decipher); + default: + KMException.throwIt(KMError.UNSUPPORTED_PURPOSE); } }else if(alg == KMType.EC){ switch(purpose){ @@ -623,9 +619,8 @@ public KMOperation initAsymmetricOperation(byte purpose, byte alg, byte padding, Signature signer = createEcSigner(digest,privKeyBuf,privKeyStart,privKeyLength); return new KMOperationImpl(signer); - case KMType.VERIFY: - Signature verifier = createEcVerifier(digest,pubModBuf,pubModStart,pubModLength); - return new KMOperationImpl(verifier); + default: + KMException.throwIt(KMError.UNSUPPORTED_PURPOSE); } } CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); @@ -1110,52 +1105,6 @@ public void addRngEntropy(byte[] num, short offset, short length) { } } - - public KMCipher createRsaCipher(short padding, short digest, byte[] modBuffer, short modOff, short modLength) { - byte cipherAlg = mapCipherAlg(KMType.RSA, (byte)padding, (byte)0); - if (cipherAlg == Cipher.ALG_RSA_PKCS1_OAEP) { - return createRsaOAEP256Cipher(KMType.ENCRYPT, (byte)digest, null,(short)0,(short)0,modBuffer,modOff,modLength); - } - Cipher rsaCipher = Cipher.getInstance(cipherAlg,false); - RSAPublicKey key = (RSAPublicKey) KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_PUBLIC, KeyBuilder.LENGTH_RSA_2048, false); - byte[] exponent = new byte[]{0x01,0x00,0x01}; - key.setExponent(exponent,(short)0,(short)3); - key.setModulus(modBuffer, modOff, modLength); - rsaCipher.init(key,Cipher.MODE_ENCRYPT); - KMCipherImpl inst = new KMCipherImpl(rsaCipher); - inst.setCipherAlgorithm(KMType.RSA); - inst.setMode(KMType.ENCRYPT); - inst.setPaddingAlgorithm(padding); - return inst; - } - - public Signature createRsaVerifier(short digest, short padding, byte[] modBuffer, short modOff, short modLength) { - short alg = mapSignature256Alg(KMType.RSA,(byte)padding); - if(digest == KMType.DIGEST_NONE || padding == KMType.PADDING_NONE) CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); - Signature rsaVerifier = Signature.getInstance((byte)alg, false); - RSAPublicKey key = (RSAPublicKey) KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_PUBLIC, KeyBuilder.LENGTH_RSA_2048, false); - byte[] exponent = new byte[]{0x01,0x00,0x01}; - key.setExponent(exponent,(short)0,(short)3); - key.setModulus(modBuffer, modOff, modLength); - rsaVerifier.init(key,Signature.MODE_VERIFY); - return rsaVerifier; - } - - public Signature createEcVerifier(short digest, byte[] pubKey, short pubKeyStart, short pubKeyLength) { - short alg = mapSignature256Alg(KMType.EC, (byte)0); - Signature ecVerifier; - //if(msgDigestAlg == MessageDigest.ALG_NULL) CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); - if(digest == KMType.DIGEST_NONE) { - ecVerifier = new KMEcdsa256NoDigestSignature(Signature.MODE_VERIFY, pubKey, pubKeyStart, pubKeyLength); - } else { - ECPublicKey key = (ECPublicKey) KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PUBLIC, KeyBuilder.LENGTH_EC_FP_256, false); - key.setW(pubKey,pubKeyStart,pubKeyLength); - ecVerifier = Signature.getInstance((byte)alg,false); - ecVerifier.init(key,Signature.MODE_VERIFY); - } - return ecVerifier; - } - @Override public KMAttestationCert getAttestationCert(boolean rsaCert) { return KMAttestationCertImpl.instance(rsaCert); diff --git a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMRsa2048NoDigestSignature.java b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMRsa2048NoDigestSignature.java index 855a3104..fc953d73 100644 --- a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMRsa2048NoDigestSignature.java +++ b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMRsa2048NoDigestSignature.java @@ -89,8 +89,7 @@ public short signPreComputedHash(byte[] bytes, short i, short i1, byte[] bytes1, @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. + // Public key operations not handled here. return false; } diff --git a/Applet/JCardSimProvider/test/com/android/javacard/test/KMFunctionalTest.java b/Applet/JCardSimProvider/test/com/android/javacard/test/KMFunctionalTest.java index a6308513..3e0653eb 100644 --- a/Applet/JCardSimProvider/test/com/android/javacard/test/KMFunctionalTest.java +++ b/Applet/JCardSimProvider/test/com/android/javacard/test/KMFunctionalTest.java @@ -44,9 +44,37 @@ import javacard.framework.AID; import javacard.framework.Util; +import javacard.security.ECPublicKey; +import javacard.security.KeyBuilder; +import javacard.security.KeyPair; +import javacard.security.RSAPublicKey; +import javacard.security.Signature; +import javacardx.crypto.Cipher; + +import java.math.BigInteger; +import java.security.AlgorithmParameters; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.KeyFactory; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.SignatureException; +import java.security.spec.ECGenParameterSpec; +import java.security.spec.ECParameterSpec; +import java.security.spec.ECPoint; +import java.security.spec.ECPublicKeySpec; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.InvalidParameterSpecException; +import java.security.spec.MGF1ParameterSpec; +import java.security.spec.RSAPublicKeySpec; import java.util.Arrays; import java.util.Random; +import javax.crypto.BadPaddingException; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.spec.OAEPParameterSpec; +import javax.crypto.spec.PSource; import javax.smartcardio.CommandAPDU; import javax.smartcardio.ResponseAPDU; @@ -776,16 +804,6 @@ public void testHmacImportKeySuccess() { @Test public void testRsaImportKeySuccess() { init(); - /* - KeyPair rsaKeyPair = cryptoProvider.createRsaKeyPair(); - byte[] pub = new byte[4]; - short len = ((RSAPublicKey)rsaKeyPair.getPublic()).getExponent(pub,(short)1); - byte[] priv = new byte[256]; - byte[] mod = new byte[256]; - len = ((RSAPrivateKey)rsaKeyPair.getPrivate()).getModulus(mod,(short)0); - len = ((RSAPrivateKey)rsaKeyPair.getPrivate()).getExponent(priv,(short)0); - */ - byte[] pub = new byte[]{0x00,0x01,0x00,0x01}; byte[] mod = new byte[256]; byte[] priv = new byte[256]; @@ -1035,13 +1053,6 @@ private short signVerificationToken(short verToken) { @Test public void testEcImportKeySuccess() { init(); - /* - KeyPair ecKeyPair = cryptoProvider.createECKeyPair(); - byte[] pub = new byte[128]; - short len = ((ECPublicKey)ecKeyPair.getPublic()).getW(pub,(short)0); - byte[] priv = new byte[128]; - len = ((ECPrivateKey)ecKeyPair.getPrivate()).getS(priv,(short)0); - */ byte[] pub = new byte[128]; byte[] priv = new byte[128]; short[] lengths = new short[2]; @@ -1107,7 +1118,7 @@ public void testEcImportKeySuccess() { cleanUp(); } - private short extractKeyBlobArray(short keyBlob) { + private short extractKeyBlobArray(byte[] buf, short off, short buflen) { short ret = KMArray.instance((short) 5); KMArray.cast(ret).add(KMKeymasterApplet.KEY_BLOB_SECRET, KMByteBlob.exp()); KMArray.cast(ret).add(KMKeymasterApplet.KEY_BLOB_AUTH_TAG, KMByteBlob.exp()); @@ -1118,15 +1129,18 @@ private short extractKeyBlobArray(short keyBlob) { ret = decoder.decodeArray( ret, - KMByteBlob.cast(keyBlob).getBuffer(), - KMByteBlob.cast(keyBlob).getStartOff(), - KMByteBlob.cast(keyBlob).length()); + buf, off, buflen); short len = KMArray.cast(ret).length(); ptr = KMArray.cast(ret).get((short)4); // print(KMByteBlob.cast(ptr).getBuffer(),KMByteBlob.cast(ptr).getStartOff(),KMByteBlob.cast(ptr).length()); return ret; } + private short extractKeyBlobArray(short keyBlob) { + return extractKeyBlobArray(KMByteBlob.cast(keyBlob).getBuffer(), KMByteBlob + .cast(keyBlob).getStartOff(), KMByteBlob.cast(keyBlob).length()); + } + @Test public void testRsaGenerateKeySuccess() { init(); @@ -1532,10 +1546,7 @@ public void testComputeHmacParams(){ KMByteBlob.cast(num).getBuffer(), KMByteBlob.cast(num).getStartOff(), KMByteBlob.cast(num).length()); - // cryptoProvider.newRandomNumber( -// KMByteBlob.cast(num).getBuffer(), -// KMByteBlob.cast(num).getStartOff(), -// KMByteBlob.cast(num).length()); + KMHmacSharingParameters.cast(params1).setNonce(num); short params2 = KMHmacSharingParameters.instance(); KMHmacSharingParameters.cast(params2).setSeed(KMByteBlob.instance((short)0)); @@ -1612,10 +1623,8 @@ public void testImportWrappedKey(){ byte[] wrappedKey = new byte[16]; cryptoProvider.newRandomNumber(wrappedKey,(short)0,(short)16); byte[] encWrappedKey = new byte[16]; - //AESKey transportKey = cryptoProvider.createAESKey((short)256); byte[] transportKeyMaterial = new byte[32]; cryptoProvider.newRandomNumber(transportKeyMaterial,(short)0,(short)32); - //transportKey.setKey(transportKeyMaterial,(short)0); byte[] nonce = new byte[12]; cryptoProvider.newRandomNumber(nonce,(short)0,(short)12); byte[] authData = "Auth Data".getBytes(); @@ -1635,17 +1644,17 @@ public void testImportWrappedKey(){ Util.arrayCopyNonAtomic(KMByteBlob.cast(keyBlobPtr).getBuffer(), KMByteBlob.cast(keyBlobPtr).getStartOff(), wrappingKeyBlob,(short)0, (short)wrappingKeyBlob.length); - short inParams = getRsaParams(KMType.SHA2_256, KMType.RSA_OAEP); - short ret = processMessage(maskedTransportKey, - KMByteBlob.instance(wrappingKeyBlob,(short)0, (short)wrappingKeyBlob.length), - KMType.ENCRYPT, - KMKeyParameters.instance(inParams), - (short)0,null,false,false - ); - keyBlobPtr = KMArray.cast(ret).get((short)2); - byte[] encTransportKey = new byte[KMByteBlob.cast(keyBlobPtr).length()]; - Util.arrayCopyNonAtomic(KMByteBlob.cast(keyBlobPtr).getBuffer(), KMByteBlob.cast(keyBlobPtr).getStartOff(), - encTransportKey,(short)0, (short)encTransportKey.length); + + byte[] output = new byte[256]; + short outlen = rsaOaepEncryptMessage(wrappingKeyBlob, KMType.SHA2_256, + maskedTransportKey, (short)0, (short)maskedTransportKey.length, + output, (short)0); + Assert.assertTrue((outlen == 256)); + byte[] encTransportKey = new byte[outlen]; + Util.arrayCopyNonAtomic(output, (short)0, encTransportKey, (short)0, + outlen); + //Clean the heap. + KMRepository.instance().clean(); short tagCount = 7; short arrPtr = KMArray.instance(tagCount); short boolTag = KMBoolTag.instance(KMType.NO_AUTH_REQUIRED); @@ -1689,7 +1698,7 @@ public void testImportWrappedKey(){ CommandAPDU apdu = encodeApdu((byte)INS_IMPORT_WRAPPED_KEY_CMD, arr); // print(commandAPDU.getBytes()); ResponseAPDU response = simulator.transmitCommand(apdu); - ret = KMArray.instance((short) 3); + short ret = KMArray.instance((short) 3); KMArray.cast(ret).add((short) 0, KMInteger.exp()); KMArray.cast(ret).add((short)1, KMByteBlob.exp()); short inst = KMKeyCharacteristics.exp(); @@ -1787,11 +1796,6 @@ public void testDeleteKeySuccess() { Assert.assertEquals(error, KMError.OK); ret = deleteKey(KMByteBlob.instance(keyBlob,(short)0,(short)keyBlob.length)); Assert.assertEquals(ret, KMError.OK); -/* ret = getKeyCharacteristics(KMByteBlob.instance(keyBlob,(short)0,(short)keyBlob.length)); - short err = KMByteBlob.cast(ret).get((short)1); - Assert.assertEquals(KMError.INVALID_KEY_BLOB,err); - - */ cleanUp(); } @@ -1811,14 +1815,6 @@ public void testDeleteAllKeySuccess() { ResponseAPDU response = simulator.transmitCommand(apdu); byte[] respBuf = response.getBytes(); Assert.assertEquals(respBuf[0], KMError.OK); -/* short ret = getKeyCharacteristics(KMByteBlob.instance(keyBlob1,(short)0,(short)keyBlob1.length)); - short err = KMByteBlob.cast(ret).get((short)1); - Assert.assertEquals(KMError.INVALID_KEY_BLOB,err); - ret = getKeyCharacteristics(KMByteBlob.instance(keyBlob2,(short)0,(short)keyBlob2.length)); - err = KMByteBlob.cast(ret).get((short)1); - Assert.assertEquals(KMError.INVALID_KEY_BLOB,err); - - */ cleanUp(); } @@ -2027,6 +2023,223 @@ public void testSignWithRsaNonePkcs1(){ cleanUp(); } + public short getPublicKey(byte[] keyBlob, short off, short len, + byte[] pubKey, short pubKeyOff) { + short keyBlobPtr = extractKeyBlobArray(keyBlob, off, len); + short arrayLen = KMArray.cast(keyBlobPtr).length(); + if (arrayLen < 5) { + return 0; + } + short pubKeyPtr = KMArray.cast(keyBlobPtr).get( + KMKeymasterApplet.KEY_BLOB_PUB_KEY); + Util.arrayCopy(KMByteBlob.cast(pubKeyPtr).getBuffer(), + KMByteBlob.cast(pubKeyPtr).getStartOff(), pubKey, pubKeyOff, + KMByteBlob.cast(pubKeyPtr).length()); + return KMByteBlob.cast(pubKeyPtr).length(); + } + + private String toHexString(byte[] num){ + StringBuilder sb = new StringBuilder(); + for(int i = 0; i < num.length; i++){ + sb.append(String.format("%02X", num[i])) ; + } + return sb.toString(); + } + + public short rsaEncryptMessage(byte[] keyBlob, short padding, short digest, byte[] input, short inputOff, short inputlen, + byte[] output, short outputOff) { + byte alg = Cipher.ALG_RSA_PKCS1; + byte[] tmp = null; + short inLen = inputlen; + if (padding == KMType.PADDING_NONE) { + alg = Cipher.ALG_RSA_NOPAD; + // Length cannot be greater then key size according to JcardSim + if(inLen >= 256) + return 0; + // make input equal to 255 bytes + tmp = new byte[255]; + Util.arrayFillNonAtomic(tmp,(short)0,(short)255, (byte)0); + Util.arrayCopyNonAtomic( + input, + inputOff, + tmp, (short)(255 - inLen),inLen); + inLen = 255; + inputOff = 0; + } else if(padding == KMType.RSA_PKCS1_1_5_ENCRYPT) { + tmp = input; + } else { + /*Fail */ + Assert.assertTrue(false); + } + byte[] pubKey = new byte[256]; + KeyPair rsaKeyPair = new KeyPair(KeyPair.ALG_RSA, KeyBuilder.LENGTH_RSA_2048); + RSAPublicKey rsaPubKey = (RSAPublicKey) rsaKeyPair.getPublic(); + if (0 == getPublicKey(keyBlob, (short)0, (short)keyBlob.length, pubKey, (short)0)) + return 0; + + byte[] exponent = new byte[]{0x01,0x00,0x01}; + rsaPubKey.setModulus(pubKey, (short) 0, (short) pubKey.length); + rsaPubKey.setExponent(exponent, (short) 0, (short) exponent.length); + + Cipher rsaCipher = Cipher.getInstance(alg, false); + rsaCipher.init(rsaPubKey, Cipher.MODE_ENCRYPT); + return rsaCipher.doFinal(tmp, inputOff, inLen, output, outputOff); + } + + public short rsaOaepEncryptMessage(byte[] keyBlob, short digest, byte[] input, short inputOff, short inputlen, + byte[] output, short outputOff) { + byte[] mod = new byte[256]; + if (0 == getPublicKey(keyBlob, (short)0, (short)keyBlob.length, mod, (short)0)) + return 0; + byte[] exponent = new byte[]{0x01,0x00,0x01}; + + // Convert byte arrays into keys + String modString = toHexString(mod); + String expString = toHexString(exponent); + BigInteger modInt = new BigInteger(modString,16); + BigInteger expInt = new BigInteger(expString,16); + javax.crypto.Cipher rsaCipher = null; + try{ + KeyFactory kf = KeyFactory.getInstance("RSA"); + // Create cipher with oaep padding + OAEPParameterSpec oaepSpec = null; + if(digest == KMType.SHA2_256){ + oaepSpec= new OAEPParameterSpec("SHA-256", "MGF1", + MGF1ParameterSpec.SHA1, PSource.PSpecified.DEFAULT); + }else{ + oaepSpec= new OAEPParameterSpec("SHA1", "MGF1", + MGF1ParameterSpec.SHA1, PSource.PSpecified.DEFAULT); + } + rsaCipher = javax.crypto.Cipher.getInstance("RSA/ECB/OAEPPadding", "SunJCE"); + + RSAPublicKeySpec pubSpec = new RSAPublicKeySpec(modInt, expInt); + java.security.interfaces.RSAPublicKey pubKey = (java.security.interfaces.RSAPublicKey) kf.generatePublic(pubSpec); + rsaCipher.init(javax.crypto.Cipher.ENCRYPT_MODE, pubKey, oaepSpec); + byte[] cipherOut = rsaCipher.doFinal(input, inputOff, inputlen); + + if(cipherOut != null) { + Util.arrayCopyNonAtomic(cipherOut, (short) 0, output, outputOff, (short) cipherOut.length); + } + return (short) cipherOut.length; + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } catch (InvalidKeySpecException e) { + e.printStackTrace(); + } catch (InvalidKeyException e) { + e.printStackTrace(); + } catch (InvalidAlgorithmParameterException e) { + e.printStackTrace(); + } catch (NoSuchPaddingException e) { + e.printStackTrace(); + } catch (NoSuchProviderException e) { + e.printStackTrace(); + } catch (IllegalBlockSizeException e) { + e.printStackTrace(); + } catch (BadPaddingException e) { + e.printStackTrace(); + } + return 0; + } + + public boolean ecNoDigestVerifyMessage(byte[] input, short inputOff, + short inputlen, byte[] sign, short signOff, short signLen, + byte[] keyBlob) { + KeyFactory kf; + byte[] pubKey = new byte[128]; + short keyStart = 0; + short keyLength = getPublicKey(keyBlob, (short) 0, (short) keyBlob.length, + pubKey, (short) 0); + if (keyLength == 0) + return false; + try { + java.security.Signature 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); + + // Check if the first byte is 04 and remove it. + if (pubKey[keyStart] == 0x04) { + // uncompressed format. + keyStart++; + keyLength--; + } + short i = 0; + byte[] pubx = new byte[keyLength / 2]; + for (; i < keyLength / 2; i++) { + pubx[i] = pubKey[keyStart + i]; + } + byte[] puby = new byte[keyLength / 2]; + for (i = 0; i < keyLength / 2; i++) { + puby[i] = pubKey[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); + java.security.interfaces.ECPublicKey ecPubkey = (java.security.interfaces.ECPublicKey) kf + .generatePublic(pubkeyspec); + sunSigner.initVerify(ecPubkey); + sunSigner.update(input, inputOff, inputlen); + return sunSigner.verify(sign, signOff, signLen); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } catch (NoSuchProviderException e) { + e.printStackTrace(); + } catch (InvalidParameterSpecException e) { + e.printStackTrace(); + } catch (InvalidKeySpecException e) { + e.printStackTrace(); + } catch (InvalidKeyException e) { + e.printStackTrace(); + } catch (SignatureException e) { + e.printStackTrace(); + } + return false; + } + + public boolean ecVerifyMessage(byte[] input, short inputOff, short inputlen, + byte[] sign, short signOff, short signLen, byte[] keyBlob) { + Signature ecVerifier; + byte[] pubKey = new byte[128]; + short len = getPublicKey(keyBlob, (short) 0, (short) keyBlob.length, + pubKey, (short) 0); + if (len == 0) { + return false; + } + ECPublicKey key = (ECPublicKey) KeyBuilder.buildKey( + KeyBuilder.TYPE_EC_FP_PUBLIC, KeyBuilder.LENGTH_EC_FP_256, false); + key.setW(pubKey, (short) 0, len); + ecVerifier = Signature.getInstance(Signature.ALG_ECDSA_SHA_256, false); + ecVerifier.init(key, Signature.MODE_VERIFY); + return ecVerifier.verify(input, inputOff, inputlen, sign, signOff, signLen); + } + + public boolean rsaVerifyMessage(byte[] input, short inputOff, short inputlen, byte[] sign, short signOff, short signLen, + short digest,short padding, byte[] keyBlob) { + if(digest == KMType.DIGEST_NONE || padding == KMType.PADDING_NONE) + return false; + byte[] pubKey = new byte[256]; + if (0 == getPublicKey(keyBlob, (short)0, (short)keyBlob.length, pubKey, (short)0)) + return false; + short alg = Signature.ALG_RSA_SHA_256_PKCS1_PSS; + + if (padding == KMType.RSA_PKCS1_1_5_SIGN) + alg = Signature.ALG_RSA_SHA_256_PKCS1; + + Signature rsaVerifier = Signature.getInstance((byte)alg, false); + RSAPublicKey key = (RSAPublicKey) KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_PUBLIC, KeyBuilder.LENGTH_RSA_2048, false); + byte[] exponent = new byte[]{0x01,0x00,0x01}; + key.setExponent(exponent,(short)0,(short)exponent.length); + key.setModulus(pubKey, (short)0, (short)pubKey.length); + rsaVerifier.init(key,Signature.MODE_VERIFY); + return rsaVerifier.verify(input, inputOff, inputlen, sign, signOff, signLen); + } + public byte[] EncryptMessage(byte[] input, short params, byte[] keyBlob) { short ret = begin(KMType.ENCRYPT, KMByteBlob.instance(keyBlob, (short) 0, (short) keyBlob.length), @@ -2141,13 +2354,19 @@ public void testVtsRsaPkcs1Success() { short pkcs1Params = getRsaParams(KMType.DIGEST_NONE, KMType.RSA_PKCS1_1_5_ENCRYPT); - byte[] cipherText1 = EncryptMessage(message, pkcs1Params, keyBlob); - Assert.assertEquals((2048 / 8), cipherText1.length); + byte[] cipherText1 = new byte[256]; + short cipherText1Len = rsaEncryptMessage(keyBlob, KMType.RSA_PKCS1_1_5_ENCRYPT, KMType.DIGEST_NONE, + message, (short)0, (short)message.length, + cipherText1, (short)0); + Assert.assertEquals((2048 / 8), cipherText1Len); pkcs1Params = getRsaParams(KMType.DIGEST_NONE, KMType.RSA_PKCS1_1_5_ENCRYPT); - byte[] cipherText2 = EncryptMessage(message, pkcs1Params, keyBlob); - Assert.assertEquals((2048 / 8), cipherText2.length); + byte[] cipherText2 = new byte[256]; + short cipherText2Len = rsaEncryptMessage(keyBlob, KMType.RSA_PKCS1_1_5_ENCRYPT, KMType.DIGEST_NONE, + message, (short)0, (short)message.length, + cipherText2, (short)0); + Assert.assertEquals((2048 / 8), cipherText2Len); // PKCS1 v1.5 randomizes padding so every result should be different. Assert.assertFalse(Arrays.equals(cipherText1, cipherText2)); @@ -2275,15 +2494,6 @@ public void testAttestEcKey(){ } public void testAttestKey(byte[] keyBlob){ - /* - short key = generateRsaKey(null,null); - short keyBlobPtr = KMArray.cast(key).get((short)1); - byte[] keyBlob= new byte[KMByteBlob.cast(keyBlobPtr).length()]; - Util.arrayCopyNonAtomic( - KMByteBlob.cast(keyBlobPtr).getBuffer(), - KMByteBlob.cast(keyBlobPtr).getStartOff(), - keyBlob,(short)0, (short)keyBlob.length); - */ short arrPtr = KMArray.instance((short)2); KMArray.cast(arrPtr).add((short)0, KMByteTag.instance(KMType.ATTESTATION_APPLICATION_ID, KMByteBlob.instance(attAppId,(short)0,(short)attAppId.length))); @@ -2471,19 +2681,19 @@ public void testEncryptDecryptWithRsa(byte digest, byte padding){ keyBlob,(short)0, (short)keyBlob.length); short inParams = getRsaParams(digest, padding); byte[] plainData = "Hello World 123!".getBytes(); + byte[] cipherData = new byte[256]; + short cipherDataLen = 0; //Encrypt - short ret = processMessage(plainData, - KMByteBlob.instance(keyBlob,(short)0, (short)keyBlob.length), - KMType.ENCRYPT, - KMKeyParameters.instance(inParams), - (short)0,null,false, false - ); + if (padding == KMType.RSA_OAEP) { + cipherDataLen = rsaOaepEncryptMessage(keyBlob, digest, plainData, + (short) 0, (short) plainData.length, cipherData, (short) 0); + } else { + cipherDataLen = rsaEncryptMessage(keyBlob, padding, digest, plainData, + (short) 0, (short) plainData.length, cipherData, (short) 0); + } + Assert.assertTrue((cipherDataLen == 256)); inParams = getRsaParams(digest, padding); - keyBlobPtr = KMArray.cast(ret).get((short)2); - byte[] cipherData = new byte[KMByteBlob.cast(keyBlobPtr).length()]; - Util.arrayCopyNonAtomic(KMByteBlob.cast(keyBlobPtr).getBuffer(), KMByteBlob.cast(keyBlobPtr).getStartOff(), - cipherData,(short)0, (short)cipherData.length); - ret = processMessage(cipherData, + short ret = processMessage(cipherData, KMByteBlob.instance(keyBlob,(short)0, (short)keyBlob.length), KMType.DECRYPT, KMKeyParameters.instance(inParams), @@ -2522,14 +2732,10 @@ public void testSignVerifyWithRsa(byte digest, byte padding, boolean update, boo Assert.assertEquals(signatureData.length,256); return; } - ret = processMessage(plainData, - KMByteBlob.instance(keyBlob,(short)0, (short)keyBlob.length), - KMType.VERIFY, - KMKeyParameters.instance(inParams), - (short)0,signatureData,update,false - ); - short error = KMInteger.cast(KMArray.cast(ret).get((short)0)).getShort(); - Assert.assertEquals(error, KMError.OK); + boolean verify = rsaVerifyMessage(plainData, (short)0, (short)plainData.length, + signatureData, (short)0, (short)signatureData.length, + digest, padding, keyBlob); + Assert.assertTrue(verify); } public void testSignVerifyWithEcdsa(byte digest, boolean update){ @@ -2553,14 +2759,17 @@ public void testSignVerifyWithEcdsa(byte digest, boolean update){ byte[] signatureData = new byte[KMByteBlob.cast(keyBlobPtr).length()]; Util.arrayCopyNonAtomic(KMByteBlob.cast(keyBlobPtr).getBuffer(), KMByteBlob.cast(keyBlobPtr).getStartOff(), signatureData,(short)0, (short)signatureData.length); - ret = processMessage(plainData, - KMByteBlob.instance(keyBlob,(short)0, (short)keyBlob.length), - KMType.VERIFY, - KMKeyParameters.instance(inParams), - (short)0,signatureData,update,false - ); - short error = KMInteger.cast(KMArray.cast(ret).get((short)0)).getShort(); - Assert.assertEquals(error, KMError.OK); + boolean verify = false; + if (digest == KMType.DIGEST_NONE) { + verify = ecNoDigestVerifyMessage(plainData, (short)0, (short)plainData.length, + signatureData, (short)0, (short)signatureData.length, + keyBlob); + } else { + verify = ecVerifyMessage(plainData, (short)0, (short)plainData.length, + signatureData, (short)0, (short)signatureData.length, + keyBlob); + } + Assert.assertTrue(verify); } public void testSignVerifyWithHmac(byte digest, boolean update){ short hmacKeyArr = generateHmacKey(null, null); diff --git a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java index abf6e670..e1e8214d 100644 --- a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java +++ b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java @@ -1613,18 +1613,6 @@ private void processFinishOperationCmd(APDU apdu) { private void finishEncryptOperation(KMOperationState op, byte[] scratchPad) { short len = KMByteBlob.cast(data[INPUT_DATA]).length(); switch (op.getAlgorithm()) { - case KMType.RSA: - // Output size is always 256 bytes - data[OUTPUT_DATA] = KMByteBlob.instance((short) 256); - Util.arrayFillNonAtomic(scratchPad, (short) 0, (short) 256, (byte) 0); - op.getOperation() - .finish( - KMByteBlob.cast(data[INPUT_DATA]).getBuffer(), - KMByteBlob.cast(data[INPUT_DATA]).getStartOff(), - KMByteBlob.cast(data[INPUT_DATA]).length(), - KMByteBlob.cast(data[OUTPUT_DATA]).getBuffer(), - KMByteBlob.cast(data[OUTPUT_DATA]).getStartOff()); - break; case KMType.AES: case KMType.DES: if (op.getAlgorithm() == KMType.AES) { @@ -1785,17 +1773,8 @@ private void finishSigningVerifyingOperation(KMOperationState op, byte[] scratch KMByteBlob.cast(data[OUTPUT_DATA]).getBuffer(), KMByteBlob.cast(data[OUTPUT_DATA]).getStartOff()); } else { - if (!op.getOperation() - .verify( - KMByteBlob.cast(data[INPUT_DATA]).getBuffer(), - KMByteBlob.cast(data[INPUT_DATA]).getStartOff(), - KMByteBlob.cast(data[INPUT_DATA]).length(), - KMByteBlob.cast(data[SIGNATURE]).getBuffer(), - KMByteBlob.cast(data[SIGNATURE]).getStartOff(), - KMByteBlob.cast(data[SIGNATURE]).length())) { - KMException.throwIt(KMError.VERIFICATION_FAILED); - } - } + KMException.throwIt(KMError.UNSUPPORTED_PURPOSE); + } } catch (CryptoException e) { KMException.throwIt(KMError.INVALID_ARGUMENT); } @@ -1818,17 +1797,8 @@ private void finishSigningVerifyingOperation(KMOperationState op, byte[] scratch (short) 0); data[OUTPUT_DATA] = KMByteBlob.instance(scratchPad, (short) 0, len); } else { - if (!op.getOperation() - .verify( - KMByteBlob.cast(data[INPUT_DATA]).getBuffer(), - KMByteBlob.cast(data[INPUT_DATA]).getStartOff(), - len, - KMByteBlob.cast(data[SIGNATURE]).getBuffer(), - KMByteBlob.cast(data[SIGNATURE]).getStartOff(), - KMByteBlob.cast(data[SIGNATURE]).length())) { - KMException.throwIt(KMError.VERIFICATION_FAILED); - } - } + KMException.throwIt(KMError.UNSUPPORTED_PURPOSE); + } break; case KMType.HMAC: // As per Keymaster HAL documentation, the length of the Hmac output can @@ -2349,6 +2319,16 @@ private void authorizeBlockModeAndMacLength(KMOperationState op) { KMIntegerTag.getShortValue(KMType.UINT_TAG, KMType.MAC_LENGTH, data[KEY_PARAMETERS]); switch (op.getAlgorithm()) { case KMType.AES: + //Validate the block mode. + switch(param) { + case KMType.ECB: + case KMType.CBC: + case KMType.CTR: + case KMType.GCM: + break; + default: + KMException.throwIt(KMError.UNSUPPORTED_BLOCK_MODE); + } if (param == KMType.INVALID_VALUE) KMException.throwIt(KMError.INVALID_ARGUMENT); if (param == KMType.GCM) { if (op.getPadding() != KMType.PADDING_NONE) { @@ -2368,6 +2348,14 @@ private void authorizeBlockModeAndMacLength(KMOperationState op) { } break; case KMType.DES: + //Validate the block mode. + switch(param) { + case KMType.ECB: + case KMType.CBC: + break; + default: + KMException.throwIt(KMError.UNSUPPORTED_BLOCK_MODE); + } if (param == KMType.INVALID_VALUE) KMException.throwIt(KMError.INVALID_ARGUMENT); break; case KMType.HMAC: @@ -2484,18 +2472,7 @@ private void beginCipherOperation(KMOperationState op) { KMByteBlob.cast(data[PUB_KEY]).getStartOff(), KMByteBlob.cast(data[PUB_KEY]).length())); } else { - op.setOperation( - seProvider.initAsymmetricOperation( - (byte) op.getPurpose(), - op.getAlgorithm(), - op.getPadding(), - op.getDigest(), - null, - (short) 0, - (short) 0, - KMByteBlob.cast(data[PUB_KEY]).getBuffer(), - KMByteBlob.cast(data[PUB_KEY]).getStartOff(), - KMByteBlob.cast(data[PUB_KEY]).length())); + KMException.throwIt(KMError.UNSUPPORTED_PURPOSE); } } catch (CryptoException exp) { KMException.throwIt(KMError.UNSUPPORTED_ALGORITHM); @@ -2548,18 +2525,7 @@ private void beginSignVerifyOperation(KMOperationState op) { KMByteBlob.cast(data[PUB_KEY]).getStartOff(), KMByteBlob.cast(data[PUB_KEY]).length())); } else { - op.setOperation( - seProvider.initAsymmetricOperation( - (byte) op.getPurpose(), - op.getAlgorithm(), - op.getPadding(), - op.getDigest(), - null, - (short) 0, - (short) 0, - KMByteBlob.cast(data[PUB_KEY]).getBuffer(), - KMByteBlob.cast(data[PUB_KEY]).getStartOff(), - KMByteBlob.cast(data[PUB_KEY]).length())); + KMException.throwIt(KMError.UNSUPPORTED_PURPOSE); } } catch (CryptoException exp) { KMException.throwIt(KMError.UNSUPPORTED_ALGORITHM); @@ -2581,18 +2547,7 @@ private void beginSignVerifyOperation(KMOperationState op) { (short) 0, (short) 0)); } else { - op.setOperation( - seProvider.initAsymmetricOperation( - (byte) op.getPurpose(), - op.getAlgorithm(), - op.getPadding(), - op.getDigest(), - null, - (short) 0, - (short) 0, - KMByteBlob.cast(data[PUB_KEY]).getBuffer(), - KMByteBlob.cast(data[PUB_KEY]).getStartOff(), - KMByteBlob.cast(data[PUB_KEY]).length())); + KMException.throwIt(KMError.UNSUPPORTED_PURPOSE); } } catch (CryptoException exp) { // Javacard does not support NO digest based signing. @@ -3584,6 +3539,9 @@ private static void createEncryptedKeyBlob(byte[] scratchPad) { makeKeyCharacteristics(scratchPad); // make root of trust blob data[ROT] = repository.readROT(); + if (data[ROT] == KMType.INVALID_VALUE) { + KMException.throwIt(KMError.UNKNOWN_ERROR); + } // make hidden key params list data[HIDDEN_PARAMETERS] = @@ -3643,6 +3601,9 @@ private static void parseEncryptedKeyBlob(byte[] scratchPad) { data[SW_PARAMETERS] = KMKeyCharacteristics.cast(data[KEY_CHARACTERISTICS]).getSoftwareEnforced(); data[ROT] = repository.readROT(); + if (data[ROT] == KMType.INVALID_VALUE) { + KMException.throwIt(KMError.UNKNOWN_ERROR); + } data[HIDDEN_PARAMETERS] = KMKeyParameters.makeHidden(data[APP_ID], data[APP_DATA], data[ROT], scratchPad); diff --git a/Applet/src/com/android/javacard/keymaster/KMRepository.java b/Applet/src/com/android/javacard/keymaster/KMRepository.java index ee7cc6a8..47ad740a 100644 --- a/Applet/src/com/android/javacard/keymaster/KMRepository.java +++ b/Applet/src/com/android/javacard/keymaster/KMRepository.java @@ -502,35 +502,40 @@ public short getOsPatch(){ } public short readROT() { + short totalLength = 0; short length = dataLength(BOOT_VERIFIED_BOOT_KEY); - length += dataLength(BOOT_VERIFIED_BOOT_HASH); - length += dataLength(BOOT_VERIFIED_BOOT_STATE); - length += dataLength(BOOT_DEVICE_LOCKED_STATUS); - short blob = KMByteBlob.instance(length); - if((length = readDataEntry( - BOOT_VERIFIED_BOOT_KEY, - KMByteBlob.cast(blob).getBuffer(), - KMByteBlob.cast(blob).getStartOff())) == 0){ - return 0; + if (length == 0) { + return KMType.INVALID_VALUE; } - if((length += readDataEntry( - BOOT_VERIFIED_BOOT_HASH, - KMByteBlob.cast(blob).getBuffer(), - (short) (KMByteBlob.cast(blob).getStartOff() + length))) == 0){ - return 0; + totalLength += length; + if ((length = dataLength(BOOT_VERIFIED_BOOT_HASH)) == 0) { + return KMType.INVALID_VALUE; } - if((length += readDataEntry( - BOOT_VERIFIED_BOOT_STATE, - KMByteBlob.cast(blob).getBuffer(), - (short) (KMByteBlob.cast(blob).getStartOff() + length))) == 0){ - return 0; + totalLength += length; + if ((length = dataLength(BOOT_VERIFIED_BOOT_STATE)) == 0) { + return KMType.INVALID_VALUE; } - if((length += readDataEntry( - BOOT_DEVICE_LOCKED_STATUS, - KMByteBlob.cast(blob).getBuffer(), - (short) (KMByteBlob.cast(blob).getStartOff() + length))) == 0){ - return 0; + totalLength += length; + if ((length = dataLength(BOOT_DEVICE_LOCKED_STATUS)) == 0) { + return KMType.INVALID_VALUE; } + totalLength += length; + + short blob = KMByteBlob.instance(totalLength); + length = readDataEntry(BOOT_VERIFIED_BOOT_KEY, KMByteBlob.cast(blob) + .getBuffer(), KMByteBlob.cast(blob).getStartOff()); + + length += readDataEntry(BOOT_VERIFIED_BOOT_HASH, KMByteBlob.cast(blob) + .getBuffer(), + (short) (KMByteBlob.cast(blob).getStartOff() + length)); + + length += readDataEntry(BOOT_VERIFIED_BOOT_STATE, KMByteBlob.cast(blob) + .getBuffer(), + (short) (KMByteBlob.cast(blob).getStartOff() + length)); + + readDataEntry(BOOT_DEVICE_LOCKED_STATUS, KMByteBlob.cast(blob) + .getBuffer(), + (short) (KMByteBlob.cast(blob).getStartOff() + length)); return blob; }