Merge "Support RSA encrypt using private key and PKCS#1 paddding." into mnc-dev
This commit is contained in:
@@ -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.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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 {}
|
||||||
|
|
||||||
@@ -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;
|
||||||
|
|
||||||
@@ -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);
|
||||||
@@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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)
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user