Loading keystore/java/android/security/keystore/AndroidKeyStoreCipherSpiBase.java +15 −0 Original line number Original line Diff line number Diff line Loading @@ -731,6 +731,21 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor return mMainDataStreamer.getProducedOutputSizeBytes(); return mMainDataStreamer.getProducedOutputSizeBytes(); } } static String opmodeToString(int opmode) { switch (opmode) { case Cipher.ENCRYPT_MODE: return "ENCRYPT_MODE"; case Cipher.DECRYPT_MODE: return "DECRYPT_MODE"; case Cipher.WRAP_MODE: return "WRAP_MODE"; case Cipher.UNWRAP_MODE: return "UNWRAP_MODE"; default: return String.valueOf(opmode); } } // The methods below need to be implemented by subclasses. // The methods below need to be implemented by subclasses. /** /** Loading keystore/java/android/security/keystore/AndroidKeyStoreRSACipherSpi.java +51 −18 Original line number Original line Diff line number Diff line Loading @@ -60,9 +60,10 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase } } @Override @Override protected boolean isEncryptingUsingPrivateKeyPermitted() { protected boolean adjustConfigForEncryptingWithPrivateKey() { // RSA encryption with no padding using private key is is a way to implement raw RSA // RSA encryption with no padding using private key is a way to implement raw RSA // signatures. We have to support this. // signatures which JCA does not expose via Signature. We thus have to support this. setKeymasterPurposeOverride(KeymasterDefs.KM_PURPOSE_SIGN); return true; return true; } } Loading Loading @@ -197,6 +198,15 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase super(KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_ENCRYPT); super(KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_ENCRYPT); } } @Override protected boolean adjustConfigForEncryptingWithPrivateKey() { // RSA encryption with PCKS#1 padding using private key is a way to implement RSA // signatures with PKCS#1 padding. We have to support this for legacy reasons. setKeymasterPurposeOverride(KeymasterDefs.KM_PURPOSE_SIGN); setKeymasterPaddingOverride(KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_SIGN); return true; } @Override @Override protected void initAlgorithmSpecificParameters() throws InvalidKeyException {} protected void initAlgorithmSpecificParameters() throws InvalidKeyException {} Loading Loading @@ -425,6 +435,7 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase } } private final int mKeymasterPadding; private final int mKeymasterPadding; private int mKeymasterPaddingOverride; private int mModulusSizeBytes = -1; private int mModulusSizeBytes = -1; Loading Loading @@ -458,20 +469,15 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase // Permitted // Permitted break; break; case Cipher.ENCRYPT_MODE: case Cipher.ENCRYPT_MODE: if (!isEncryptingUsingPrivateKeyPermitted()) { case Cipher.WRAP_MODE: if (!adjustConfigForEncryptingWithPrivateKey()) { throw new InvalidKeyException( throw new InvalidKeyException( "RSA private keys cannot be used with Cipher.ENCRYPT_MODE" "RSA private keys cannot be used with " + opmodeToString(opmode) + " and padding " + KeyProperties.EncryptionPadding.fromKeymaster(mKeymasterPadding) + ". Only RSA public keys supported for this 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; 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: default: throw new InvalidKeyException( throw new InvalidKeyException( "RSA private keys cannot be used with opmode: " + opmode); "RSA private keys cannot be used with opmode: " + opmode); Loading @@ -485,12 +491,15 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase break; break; case Cipher.DECRYPT_MODE: case Cipher.DECRYPT_MODE: case Cipher.UNWRAP_MODE: case Cipher.UNWRAP_MODE: throw new InvalidKeyException("RSA public keys cannot be used with opmode: " throw new InvalidKeyException( + opmode + ". Only RSA private keys supported for this opmode."); "RSA public keys cannot be used with " + opmodeToString(opmode) + " and padding " + KeyProperties.EncryptionPadding.fromKeymaster(mKeymasterPadding) + ". Only RSA private keys supported for this opmode."); // break; // break; default: default: throw new InvalidKeyException( throw new InvalidKeyException( "RSA public keys cannot be used with opmode: " + opmode); "RSA public keys cannot be used with " + opmodeToString(opmode)); } } } } Loading @@ -511,13 +520,22 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase setKey(keystoreKey); setKey(keystoreKey); } } protected boolean isEncryptingUsingPrivateKeyPermitted() { /** * Adjusts the configuration of this cipher for encrypting using the private key. * * <p>The default implementation does nothing and refuses to adjust the configuration. * * @return {@code true} if the configuration has been adjusted, {@code false} if encrypting * using private key is not permitted for this cipher. */ protected boolean adjustConfigForEncryptingWithPrivateKey() { return false; return false; } } @Override @Override protected final void resetAll() { protected final void resetAll() { mModulusSizeBytes = -1; mModulusSizeBytes = -1; mKeymasterPaddingOverride = -1; super.resetAll(); super.resetAll(); } } Loading @@ -530,7 +548,11 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase protected void addAlgorithmSpecificParametersToBegin( protected void addAlgorithmSpecificParametersToBegin( @NonNull KeymasterArguments keymasterArgs) { @NonNull KeymasterArguments keymasterArgs) { keymasterArgs.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_RSA); keymasterArgs.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_RSA); keymasterArgs.addEnum(KeymasterDefs.KM_TAG_PADDING, mKeymasterPadding); int keymasterPadding = getKeymasterPaddingOverride(); if (keymasterPadding == -1) { keymasterPadding = mKeymasterPadding; } keymasterArgs.addEnum(KeymasterDefs.KM_TAG_PADDING, keymasterPadding); int purposeOverride = getKeymasterPurposeOverride(); int purposeOverride = getKeymasterPurposeOverride(); if ((purposeOverride != -1) if ((purposeOverride != -1) && ((purposeOverride == KeymasterDefs.KM_PURPOSE_SIGN) && ((purposeOverride == KeymasterDefs.KM_PURPOSE_SIGN) Loading Loading @@ -568,4 +590,15 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase } } return mModulusSizeBytes; return mModulusSizeBytes; } } /** * Overrides the default padding of the crypto operation. */ protected final void setKeymasterPaddingOverride(int keymasterPadding) { mKeymasterPaddingOverride = keymasterPadding; } protected final int getKeymasterPaddingOverride() { return mKeymasterPaddingOverride; } } } Loading
keystore/java/android/security/keystore/AndroidKeyStoreCipherSpiBase.java +15 −0 Original line number Original line Diff line number Diff line Loading @@ -731,6 +731,21 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor return mMainDataStreamer.getProducedOutputSizeBytes(); return mMainDataStreamer.getProducedOutputSizeBytes(); } } static String opmodeToString(int opmode) { switch (opmode) { case Cipher.ENCRYPT_MODE: return "ENCRYPT_MODE"; case Cipher.DECRYPT_MODE: return "DECRYPT_MODE"; case Cipher.WRAP_MODE: return "WRAP_MODE"; case Cipher.UNWRAP_MODE: return "UNWRAP_MODE"; default: return String.valueOf(opmode); } } // The methods below need to be implemented by subclasses. // The methods below need to be implemented by subclasses. /** /** Loading
keystore/java/android/security/keystore/AndroidKeyStoreRSACipherSpi.java +51 −18 Original line number Original line Diff line number Diff line Loading @@ -60,9 +60,10 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase } } @Override @Override protected boolean isEncryptingUsingPrivateKeyPermitted() { protected boolean adjustConfigForEncryptingWithPrivateKey() { // RSA encryption with no padding using private key is is a way to implement raw RSA // RSA encryption with no padding using private key is a way to implement raw RSA // signatures. We have to support this. // signatures which JCA does not expose via Signature. We thus have to support this. setKeymasterPurposeOverride(KeymasterDefs.KM_PURPOSE_SIGN); return true; return true; } } Loading Loading @@ -197,6 +198,15 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase super(KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_ENCRYPT); super(KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_ENCRYPT); } } @Override protected boolean adjustConfigForEncryptingWithPrivateKey() { // RSA encryption with PCKS#1 padding using private key is a way to implement RSA // signatures with PKCS#1 padding. We have to support this for legacy reasons. setKeymasterPurposeOverride(KeymasterDefs.KM_PURPOSE_SIGN); setKeymasterPaddingOverride(KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_SIGN); return true; } @Override @Override protected void initAlgorithmSpecificParameters() throws InvalidKeyException {} protected void initAlgorithmSpecificParameters() throws InvalidKeyException {} Loading Loading @@ -425,6 +435,7 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase } } private final int mKeymasterPadding; private final int mKeymasterPadding; private int mKeymasterPaddingOverride; private int mModulusSizeBytes = -1; private int mModulusSizeBytes = -1; Loading Loading @@ -458,20 +469,15 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase // Permitted // Permitted break; break; case Cipher.ENCRYPT_MODE: case Cipher.ENCRYPT_MODE: if (!isEncryptingUsingPrivateKeyPermitted()) { case Cipher.WRAP_MODE: if (!adjustConfigForEncryptingWithPrivateKey()) { throw new InvalidKeyException( throw new InvalidKeyException( "RSA private keys cannot be used with Cipher.ENCRYPT_MODE" "RSA private keys cannot be used with " + opmodeToString(opmode) + " and padding " + KeyProperties.EncryptionPadding.fromKeymaster(mKeymasterPadding) + ". Only RSA public keys supported for this 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; 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: default: throw new InvalidKeyException( throw new InvalidKeyException( "RSA private keys cannot be used with opmode: " + opmode); "RSA private keys cannot be used with opmode: " + opmode); Loading @@ -485,12 +491,15 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase break; break; case Cipher.DECRYPT_MODE: case Cipher.DECRYPT_MODE: case Cipher.UNWRAP_MODE: case Cipher.UNWRAP_MODE: throw new InvalidKeyException("RSA public keys cannot be used with opmode: " throw new InvalidKeyException( + opmode + ". Only RSA private keys supported for this opmode."); "RSA public keys cannot be used with " + opmodeToString(opmode) + " and padding " + KeyProperties.EncryptionPadding.fromKeymaster(mKeymasterPadding) + ". Only RSA private keys supported for this opmode."); // break; // break; default: default: throw new InvalidKeyException( throw new InvalidKeyException( "RSA public keys cannot be used with opmode: " + opmode); "RSA public keys cannot be used with " + opmodeToString(opmode)); } } } } Loading @@ -511,13 +520,22 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase setKey(keystoreKey); setKey(keystoreKey); } } protected boolean isEncryptingUsingPrivateKeyPermitted() { /** * Adjusts the configuration of this cipher for encrypting using the private key. * * <p>The default implementation does nothing and refuses to adjust the configuration. * * @return {@code true} if the configuration has been adjusted, {@code false} if encrypting * using private key is not permitted for this cipher. */ protected boolean adjustConfigForEncryptingWithPrivateKey() { return false; return false; } } @Override @Override protected final void resetAll() { protected final void resetAll() { mModulusSizeBytes = -1; mModulusSizeBytes = -1; mKeymasterPaddingOverride = -1; super.resetAll(); super.resetAll(); } } Loading @@ -530,7 +548,11 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase protected void addAlgorithmSpecificParametersToBegin( protected void addAlgorithmSpecificParametersToBegin( @NonNull KeymasterArguments keymasterArgs) { @NonNull KeymasterArguments keymasterArgs) { keymasterArgs.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_RSA); keymasterArgs.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_RSA); keymasterArgs.addEnum(KeymasterDefs.KM_TAG_PADDING, mKeymasterPadding); int keymasterPadding = getKeymasterPaddingOverride(); if (keymasterPadding == -1) { keymasterPadding = mKeymasterPadding; } keymasterArgs.addEnum(KeymasterDefs.KM_TAG_PADDING, keymasterPadding); int purposeOverride = getKeymasterPurposeOverride(); int purposeOverride = getKeymasterPurposeOverride(); if ((purposeOverride != -1) if ((purposeOverride != -1) && ((purposeOverride == KeymasterDefs.KM_PURPOSE_SIGN) && ((purposeOverride == KeymasterDefs.KM_PURPOSE_SIGN) Loading Loading @@ -568,4 +590,15 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase } } return mModulusSizeBytes; return mModulusSizeBytes; } } /** * Overrides the default padding of the crypto operation. */ protected final void setKeymasterPaddingOverride(int keymasterPadding) { mKeymasterPaddingOverride = keymasterPadding; } protected final int getKeymasterPaddingOverride() { return mKeymasterPaddingOverride; } } }