summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--keystore/java/android/security/keystore/AndroidKeyStoreCipherSpiBase.java15
-rw-r--r--keystore/java/android/security/keystore/AndroidKeyStoreRSACipherSpi.java69
2 files changed, 66 insertions, 18 deletions
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreCipherSpiBase.java b/keystore/java/android/security/keystore/AndroidKeyStoreCipherSpiBase.java
index 50f3ed4..38cacd0 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreCipherSpiBase.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreCipherSpiBase.java
@@ -731,6 +731,21 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor
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.
/**
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreRSACipherSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreRSACipherSpi.java
index 8e58195..94ed8b4 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreRSACipherSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreRSACipherSpi.java
@@ -60,9 +60,10 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase
}
@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.
+ protected boolean adjustConfigForEncryptingWithPrivateKey() {
+ // RSA encryption with no padding using private key is a way to implement raw RSA
+ // signatures which JCA does not expose via Signature. We thus have to support this.
+ setKeymasterPurposeOverride(KeymasterDefs.KM_PURPOSE_SIGN);
return true;
}
@@ -198,6 +199,15 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase
}
@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
protected void initAlgorithmSpecificParameters() throws InvalidKeyException {}
@Override
@@ -425,6 +435,7 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase
}
private final int mKeymasterPadding;
+ private int mKeymasterPaddingOverride;
private int mModulusSizeBytes = -1;
@@ -458,20 +469,15 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase
// Permitted
break;
case Cipher.ENCRYPT_MODE:
- if (!isEncryptingUsingPrivateKeyPermitted()) {
+ case Cipher.WRAP_MODE:
+ if (!adjustConfigForEncryptingWithPrivateKey()) {
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");
}
- // 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);
@@ -485,12 +491,15 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase
break;
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.");
+ throw new InvalidKeyException(
+ "RSA public keys cannot be used with " + opmodeToString(opmode)
+ + " and padding "
+ + KeyProperties.EncryptionPadding.fromKeymaster(mKeymasterPadding)
+ + ". Only RSA private keys supported for this opmode.");
// break;
default:
throw new InvalidKeyException(
- "RSA public keys cannot be used with opmode: " + opmode);
+ "RSA public keys cannot be used with " + opmodeToString(opmode));
}
}
@@ -511,13 +520,22 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase
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;
}
@Override
protected final void resetAll() {
mModulusSizeBytes = -1;
+ mKeymasterPaddingOverride = -1;
super.resetAll();
}
@@ -530,7 +548,11 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase
protected void addAlgorithmSpecificParametersToBegin(
@NonNull KeymasterArguments keymasterArgs) {
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();
if ((purposeOverride != -1)
&& ((purposeOverride == KeymasterDefs.KM_PURPOSE_SIGN)
@@ -568,4 +590,15 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase
}
return mModulusSizeBytes;
}
+
+ /**
+ * Overrides the default padding of the crypto operation.
+ */
+ protected final void setKeymasterPaddingOverride(int keymasterPadding) {
+ mKeymasterPaddingOverride = keymasterPadding;
+ }
+
+ protected final int getKeymasterPaddingOverride() {
+ return mKeymasterPaddingOverride;
+ }
}