Loading keystore/java/android/security/keystore/AndroidKeyStoreCipherSpiBase.java +24 −4 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor // Fields below are populated by Cipher.init and KeyStore.begin and should be preserved after // doFinal finishes. private boolean mEncrypting; private int mKeymasterPurposeOverride = -1; private AndroidKeyStoreKey mKey; private SecureRandom mRng; Loading Loading @@ -165,6 +166,7 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor mKeyStore.abort(operationToken); } mEncrypting = false; mKeymasterPurposeOverride = -1; mKey = null; mRng = null; mOperationToken = null; Loading Loading @@ -210,9 +212,16 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor byte[] additionalEntropy = KeyStoreCryptoOperationUtils.getRandomBytesToMixIntoKeystoreRng( mRng, getAdditionalEntropyAmountForBegin()); int purpose; if (mKeymasterPurposeOverride != -1) { purpose = mKeymasterPurposeOverride; } else { purpose = mEncrypting ? KeymasterDefs.KM_PURPOSE_ENCRYPT : KeymasterDefs.KM_PURPOSE_DECRYPT; } OperationResult opResult = mKeyStore.begin( mKey.getAlias(), mEncrypting ? KeymasterDefs.KM_PURPOSE_ENCRYPT : KeymasterDefs.KM_PURPOSE_DECRYPT, purpose, true, // permit aborting this operation if keystore runs out of resources keymasterInputArgs, additionalEntropy); Loading Loading @@ -346,11 +355,11 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor } catch (KeyStoreException e) { switch (e.getErrorCode()) { case KeymasterDefs.KM_ERROR_INVALID_INPUT_LENGTH: throw new IllegalBlockSizeException(); throw (IllegalBlockSizeException) new IllegalBlockSizeException().initCause(e); case KeymasterDefs.KM_ERROR_INVALID_ARGUMENT: throw new BadPaddingException(); throw (BadPaddingException) new BadPaddingException().initCause(e); case KeymasterDefs.KM_ERROR_VERIFICATION_FAILED: throw new AEADBadTagException(); throw (AEADBadTagException) new AEADBadTagException().initCause(e); default: throw (IllegalBlockSizeException) new IllegalBlockSizeException().initCause(e); } Loading Loading @@ -436,6 +445,17 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor mKey = key; } /** * Overrides the default purpose/type of the crypto operation. */ protected final void setKeymasterPurposeOverride(int keymasterPurpose) { mKeymasterPurposeOverride = keymasterPurpose; } protected final int getKeymasterPurposeOverride() { return mKeymasterPurposeOverride; } /** * Returns {@code true} if this cipher is initialized for encryption, {@code false} if this * cipher is initialized for decryption. Loading keystore/java/android/security/keystore/AndroidKeyStoreRSACipherSpi.java +61 −8 Original line number Diff line number Diff line Loading @@ -59,6 +59,13 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase super(KeymasterDefs.KM_PAD_NONE); } @Override protected boolean isEncryptingUsingPrivateKeyPermitted() { // RSA encryption with no padding using private key is is a way to implement raw RSA // signatures. We have to support this. return true; } @Override protected void initAlgorithmSpecificParameters() throws InvalidKeyException {} Loading Loading @@ -152,8 +159,11 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase paddedInput.length - bufferedInput.length, bufferedInput.length); } else { // No need to pad input paddedInput = bufferedInput; // RI throws BadPaddingException in this scenario. INVALID_ARGUMENT below will // be translated into BadPaddingException. throw new KeyStoreException(KeymasterDefs.KM_ERROR_INVALID_ARGUMENT, "Message size (" + bufferedInput.length + " bytes) must be smaller than" + " modulus (" + mModulusSizeBytes + " bytes)"); } return mDelegate.doFinal(paddedInput, 0, paddedInput.length); } Loading Loading @@ -412,14 +422,46 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase } if (keystoreKey instanceof PrivateKey) { if ((opmode != Cipher.DECRYPT_MODE) && (opmode != Cipher.UNWRAP_MODE)) { throw new InvalidKeyException("Private key cannot be used with opmode: " + opmode + ". Only DECRYPT_MODE and UNWRAP_MODE supported"); // Private key switch (opmode) { case Cipher.DECRYPT_MODE: case Cipher.UNWRAP_MODE: // Permitted break; case Cipher.ENCRYPT_MODE: if (!isEncryptingUsingPrivateKeyPermitted()) { throw new InvalidKeyException( "RSA private keys cannot be used with Cipher.ENCRYPT_MODE" + ". Only RSA public keys supported for this mode"); } // JCA doesn't provide a way to generate raw RSA signatures (with arbitrary // padding). Thus, encrypting with private key is used instead. setKeymasterPurposeOverride(KeymasterDefs.KM_PURPOSE_SIGN); break; case Cipher.WRAP_MODE: throw new InvalidKeyException( "RSA private keys cannot be used with Cipher.WRAP_MODE" + ". Only RSA public keys supported for this mode"); // break; default: throw new InvalidKeyException( "RSA private keys cannot be used with opmode: " + opmode); } } else { if ((opmode != Cipher.ENCRYPT_MODE) && (opmode != Cipher.WRAP_MODE)) { throw new InvalidKeyException("Public key cannot be used with opmode: " + opmode + ". Only ENCRYPT_MODE and WRAP_MODE supported"); // Public key switch (opmode) { case Cipher.ENCRYPT_MODE: case Cipher.WRAP_MODE: // Permitted return; case Cipher.DECRYPT_MODE: case Cipher.UNWRAP_MODE: throw new InvalidKeyException("RSA public keys cannot be used with opmode: " + opmode + ". Only RSA private keys supported for this opmode."); // break; default: throw new InvalidKeyException( "RSA public keys cannot be used with opmode: " + opmode); } } Loading @@ -438,6 +480,10 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase setKey(keystoreKey); } protected boolean isEncryptingUsingPrivateKeyPermitted() { return false; } @Override protected final void resetAll() { mModulusSizeBytes = -1; Loading @@ -454,6 +500,13 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase @NonNull KeymasterArguments keymasterArgs) { keymasterArgs.addInt(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_RSA); keymasterArgs.addInt(KeymasterDefs.KM_TAG_PADDING, mKeymasterPadding); int purposeOverride = getKeymasterPurposeOverride(); if ((purposeOverride != -1) && ((purposeOverride == KeymasterDefs.KM_PURPOSE_SIGN) || (purposeOverride == KeymasterDefs.KM_PURPOSE_VERIFY))) { // Keymaster sign/verify requires digest to be specified. For raw sign/verify it's NONE. keymasterArgs.addInt(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_NONE); } } @Override Loading Loading
keystore/java/android/security/keystore/AndroidKeyStoreCipherSpiBase.java +24 −4 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor // Fields below are populated by Cipher.init and KeyStore.begin and should be preserved after // doFinal finishes. private boolean mEncrypting; private int mKeymasterPurposeOverride = -1; private AndroidKeyStoreKey mKey; private SecureRandom mRng; Loading Loading @@ -165,6 +166,7 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor mKeyStore.abort(operationToken); } mEncrypting = false; mKeymasterPurposeOverride = -1; mKey = null; mRng = null; mOperationToken = null; Loading Loading @@ -210,9 +212,16 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor byte[] additionalEntropy = KeyStoreCryptoOperationUtils.getRandomBytesToMixIntoKeystoreRng( mRng, getAdditionalEntropyAmountForBegin()); int purpose; if (mKeymasterPurposeOverride != -1) { purpose = mKeymasterPurposeOverride; } else { purpose = mEncrypting ? KeymasterDefs.KM_PURPOSE_ENCRYPT : KeymasterDefs.KM_PURPOSE_DECRYPT; } OperationResult opResult = mKeyStore.begin( mKey.getAlias(), mEncrypting ? KeymasterDefs.KM_PURPOSE_ENCRYPT : KeymasterDefs.KM_PURPOSE_DECRYPT, purpose, true, // permit aborting this operation if keystore runs out of resources keymasterInputArgs, additionalEntropy); Loading Loading @@ -346,11 +355,11 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor } catch (KeyStoreException e) { switch (e.getErrorCode()) { case KeymasterDefs.KM_ERROR_INVALID_INPUT_LENGTH: throw new IllegalBlockSizeException(); throw (IllegalBlockSizeException) new IllegalBlockSizeException().initCause(e); case KeymasterDefs.KM_ERROR_INVALID_ARGUMENT: throw new BadPaddingException(); throw (BadPaddingException) new BadPaddingException().initCause(e); case KeymasterDefs.KM_ERROR_VERIFICATION_FAILED: throw new AEADBadTagException(); throw (AEADBadTagException) new AEADBadTagException().initCause(e); default: throw (IllegalBlockSizeException) new IllegalBlockSizeException().initCause(e); } Loading Loading @@ -436,6 +445,17 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor mKey = key; } /** * Overrides the default purpose/type of the crypto operation. */ protected final void setKeymasterPurposeOverride(int keymasterPurpose) { mKeymasterPurposeOverride = keymasterPurpose; } protected final int getKeymasterPurposeOverride() { return mKeymasterPurposeOverride; } /** * Returns {@code true} if this cipher is initialized for encryption, {@code false} if this * cipher is initialized for decryption. Loading
keystore/java/android/security/keystore/AndroidKeyStoreRSACipherSpi.java +61 −8 Original line number Diff line number Diff line Loading @@ -59,6 +59,13 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase super(KeymasterDefs.KM_PAD_NONE); } @Override protected boolean isEncryptingUsingPrivateKeyPermitted() { // RSA encryption with no padding using private key is is a way to implement raw RSA // signatures. We have to support this. return true; } @Override protected void initAlgorithmSpecificParameters() throws InvalidKeyException {} Loading Loading @@ -152,8 +159,11 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase paddedInput.length - bufferedInput.length, bufferedInput.length); } else { // No need to pad input paddedInput = bufferedInput; // RI throws BadPaddingException in this scenario. INVALID_ARGUMENT below will // be translated into BadPaddingException. throw new KeyStoreException(KeymasterDefs.KM_ERROR_INVALID_ARGUMENT, "Message size (" + bufferedInput.length + " bytes) must be smaller than" + " modulus (" + mModulusSizeBytes + " bytes)"); } return mDelegate.doFinal(paddedInput, 0, paddedInput.length); } Loading Loading @@ -412,14 +422,46 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase } if (keystoreKey instanceof PrivateKey) { if ((opmode != Cipher.DECRYPT_MODE) && (opmode != Cipher.UNWRAP_MODE)) { throw new InvalidKeyException("Private key cannot be used with opmode: " + opmode + ". Only DECRYPT_MODE and UNWRAP_MODE supported"); // Private key switch (opmode) { case Cipher.DECRYPT_MODE: case Cipher.UNWRAP_MODE: // Permitted break; case Cipher.ENCRYPT_MODE: if (!isEncryptingUsingPrivateKeyPermitted()) { throw new InvalidKeyException( "RSA private keys cannot be used with Cipher.ENCRYPT_MODE" + ". Only RSA public keys supported for this mode"); } // JCA doesn't provide a way to generate raw RSA signatures (with arbitrary // padding). Thus, encrypting with private key is used instead. setKeymasterPurposeOverride(KeymasterDefs.KM_PURPOSE_SIGN); break; case Cipher.WRAP_MODE: throw new InvalidKeyException( "RSA private keys cannot be used with Cipher.WRAP_MODE" + ". Only RSA public keys supported for this mode"); // break; default: throw new InvalidKeyException( "RSA private keys cannot be used with opmode: " + opmode); } } else { if ((opmode != Cipher.ENCRYPT_MODE) && (opmode != Cipher.WRAP_MODE)) { throw new InvalidKeyException("Public key cannot be used with opmode: " + opmode + ". Only ENCRYPT_MODE and WRAP_MODE supported"); // Public key switch (opmode) { case Cipher.ENCRYPT_MODE: case Cipher.WRAP_MODE: // Permitted return; case Cipher.DECRYPT_MODE: case Cipher.UNWRAP_MODE: throw new InvalidKeyException("RSA public keys cannot be used with opmode: " + opmode + ". Only RSA private keys supported for this opmode."); // break; default: throw new InvalidKeyException( "RSA public keys cannot be used with opmode: " + opmode); } } Loading @@ -438,6 +480,10 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase setKey(keystoreKey); } protected boolean isEncryptingUsingPrivateKeyPermitted() { return false; } @Override protected final void resetAll() { mModulusSizeBytes = -1; Loading @@ -454,6 +500,13 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase @NonNull KeymasterArguments keymasterArgs) { keymasterArgs.addInt(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_RSA); keymasterArgs.addInt(KeymasterDefs.KM_TAG_PADDING, mKeymasterPadding); int purposeOverride = getKeymasterPurposeOverride(); if ((purposeOverride != -1) && ((purposeOverride == KeymasterDefs.KM_PURPOSE_SIGN) || (purposeOverride == KeymasterDefs.KM_PURPOSE_VERIFY))) { // Keymaster sign/verify requires digest to be specified. For raw sign/verify it's NONE. keymasterArgs.addInt(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_NONE); } } @Override Loading