Merge "Keystore: Included KM_TAG_RSA_OAEP_MGF_DIGEST tag" am: eea63d6aa4 am: f42d5e8847 am: 72b1cc3e49 am: 3f20176ddf
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/2167462 Change-Id: I0dcc2afa940a582e017420a9ddbe3d92674f07ed Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -68,6 +68,8 @@ public final class KeymasterDefs {
|
|||||||
|
|
||||||
public static final int KM_TAG_RSA_PUBLIC_EXPONENT = Tag.RSA_PUBLIC_EXPONENT; // KM_ULONG | 200;
|
public static final int KM_TAG_RSA_PUBLIC_EXPONENT = Tag.RSA_PUBLIC_EXPONENT; // KM_ULONG | 200;
|
||||||
public static final int KM_TAG_INCLUDE_UNIQUE_ID = Tag.INCLUDE_UNIQUE_ID; // KM_BOOL | 202;
|
public static final int KM_TAG_INCLUDE_UNIQUE_ID = Tag.INCLUDE_UNIQUE_ID; // KM_BOOL | 202;
|
||||||
|
public static final int KM_TAG_RSA_OAEP_MGF_DIGEST = Tag.RSA_OAEP_MGF_DIGEST;
|
||||||
|
// KM_ENUM_REP | 203;
|
||||||
|
|
||||||
public static final int KM_TAG_ACTIVE_DATETIME = Tag.ACTIVE_DATETIME; // KM_DATE | 400;
|
public static final int KM_TAG_ACTIVE_DATETIME = Tag.ACTIVE_DATETIME; // KM_DATE | 400;
|
||||||
public static final int KM_TAG_ORIGINATION_EXPIRE_DATETIME =
|
public static final int KM_TAG_ORIGINATION_EXPIRE_DATETIME =
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ import libcore.util.EmptyArray;
|
|||||||
|
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.security.spec.AlgorithmParameterSpec;
|
||||||
|
import java.security.spec.MGF1ParameterSpec;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
@@ -675,6 +677,26 @@ public abstract class KeyProperties {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@NonNull public static @DigestEnum
|
||||||
|
AlgorithmParameterSpec fromKeymasterToMGF1ParameterSpec(int digest) {
|
||||||
|
switch (digest) {
|
||||||
|
default:
|
||||||
|
case KeymasterDefs.KM_DIGEST_SHA1:
|
||||||
|
return MGF1ParameterSpec.SHA1;
|
||||||
|
case KeymasterDefs.KM_DIGEST_SHA_2_224:
|
||||||
|
return MGF1ParameterSpec.SHA224;
|
||||||
|
case KeymasterDefs.KM_DIGEST_SHA_2_256:
|
||||||
|
return MGF1ParameterSpec.SHA256;
|
||||||
|
case KeymasterDefs.KM_DIGEST_SHA_2_384:
|
||||||
|
return MGF1ParameterSpec.SHA384;
|
||||||
|
case KeymasterDefs.KM_DIGEST_SHA_2_512:
|
||||||
|
return MGF1ParameterSpec.SHA512;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
public static @DigestEnum String fromKeymasterToSignatureAlgorithmDigest(int digest) {
|
public static @DigestEnum String fromKeymasterToSignatureAlgorithmDigest(int digest) {
|
||||||
switch (digest) {
|
switch (digest) {
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ import javax.crypto.spec.SecretKeySpec;
|
|||||||
*/
|
*/
|
||||||
abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStoreCryptoOperation {
|
abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStoreCryptoOperation {
|
||||||
private static final String TAG = "AndroidKeyStoreCipherSpiBase";
|
private static final String TAG = "AndroidKeyStoreCipherSpiBase";
|
||||||
|
public static final String DEFAULT_MGF1_DIGEST = "SHA-1";
|
||||||
|
|
||||||
// Fields below are populated by Cipher.init and KeyStore.begin and should be preserved after
|
// Fields below are populated by Cipher.init and KeyStore.begin and should be preserved after
|
||||||
// doFinal finishes.
|
// doFinal finishes.
|
||||||
@@ -133,24 +134,28 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor
|
|||||||
if ("RSA/ECB/OAEPWithSHA-224AndMGF1Padding".equals(transform)) {
|
if ("RSA/ECB/OAEPWithSHA-224AndMGF1Padding".equals(transform)) {
|
||||||
OAEPParameterSpec spec =
|
OAEPParameterSpec spec =
|
||||||
new OAEPParameterSpec("SHA-224", "MGF1",
|
new OAEPParameterSpec("SHA-224", "MGF1",
|
||||||
new MGF1ParameterSpec("SHA1"), PSource.PSpecified.DEFAULT);
|
new MGF1ParameterSpec(DEFAULT_MGF1_DIGEST),
|
||||||
|
PSource.PSpecified.DEFAULT);
|
||||||
mCipher.init(opmode, key, spec, random);
|
mCipher.init(opmode, key, spec, random);
|
||||||
} else if ("RSA/ECB/OAEPWithSHA-256AndMGF1Padding".equals(transform)) {
|
} else if ("RSA/ECB/OAEPWithSHA-256AndMGF1Padding".equals(transform)) {
|
||||||
OAEPParameterSpec spec =
|
OAEPParameterSpec spec =
|
||||||
new OAEPParameterSpec("SHA-256", "MGF1",
|
new OAEPParameterSpec("SHA-256", "MGF1",
|
||||||
new MGF1ParameterSpec("SHA1"), PSource.PSpecified.DEFAULT);
|
new MGF1ParameterSpec(DEFAULT_MGF1_DIGEST),
|
||||||
|
PSource.PSpecified.DEFAULT);
|
||||||
mCipher.init(opmode, key, spec, random);
|
mCipher.init(opmode, key, spec, random);
|
||||||
|
|
||||||
} else if ("RSA/ECB/OAEPWithSHA-384AndMGF1Padding".equals(transform)) {
|
} else if ("RSA/ECB/OAEPWithSHA-384AndMGF1Padding".equals(transform)) {
|
||||||
OAEPParameterSpec spec =
|
OAEPParameterSpec spec =
|
||||||
new OAEPParameterSpec("SHA-384", "MGF1",
|
new OAEPParameterSpec("SHA-384", "MGF1",
|
||||||
new MGF1ParameterSpec("SHA1"), PSource.PSpecified.DEFAULT);
|
new MGF1ParameterSpec(DEFAULT_MGF1_DIGEST),
|
||||||
|
PSource.PSpecified.DEFAULT);
|
||||||
mCipher.init(opmode, key, spec, random);
|
mCipher.init(opmode, key, spec, random);
|
||||||
|
|
||||||
} else if ("RSA/ECB/OAEPWithSHA-512AndMGF1Padding".equals(transform)) {
|
} else if ("RSA/ECB/OAEPWithSHA-512AndMGF1Padding".equals(transform)) {
|
||||||
OAEPParameterSpec spec =
|
OAEPParameterSpec spec =
|
||||||
new OAEPParameterSpec("SHA-512", "MGF1",
|
new OAEPParameterSpec("SHA-512", "MGF1",
|
||||||
new MGF1ParameterSpec("SHA1"), PSource.PSpecified.DEFAULT);
|
new MGF1ParameterSpec(DEFAULT_MGF1_DIGEST),
|
||||||
|
PSource.PSpecified.DEFAULT);
|
||||||
mCipher.init(opmode, key, spec, random);
|
mCipher.init(opmode, key, spec, random);
|
||||||
} else {
|
} else {
|
||||||
mCipher.init(opmode, key, random);
|
mCipher.init(opmode, key, random);
|
||||||
|
|||||||
@@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package android.security.keystore2;
|
package android.security.keystore2;
|
||||||
|
|
||||||
|
import static android.security.keystore2.AndroidKeyStoreCipherSpiBase.DEFAULT_MGF1_DIGEST;
|
||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.app.ActivityThread;
|
import android.app.ActivityThread;
|
||||||
@@ -908,6 +910,26 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
|
|||||||
params.add(KeyStore2ParameterUtils.makeEnum(
|
params.add(KeyStore2ParameterUtils.makeEnum(
|
||||||
KeymasterDefs.KM_TAG_PADDING, padding
|
KeymasterDefs.KM_TAG_PADDING, padding
|
||||||
));
|
));
|
||||||
|
if (padding == KeymasterDefs.KM_PAD_RSA_OAEP) {
|
||||||
|
final boolean[] hasDefaultMgf1DigestBeenAdded = {false};
|
||||||
|
ArrayUtils.forEach(mKeymasterDigests, (digest) -> {
|
||||||
|
params.add(KeyStore2ParameterUtils.makeEnum(
|
||||||
|
KeymasterDefs.KM_TAG_RSA_OAEP_MGF_DIGEST, digest
|
||||||
|
));
|
||||||
|
hasDefaultMgf1DigestBeenAdded[0] |=
|
||||||
|
digest.equals(KeyProperties.Digest.toKeymaster(DEFAULT_MGF1_DIGEST));
|
||||||
|
});
|
||||||
|
/* Because of default MGF1 digest is SHA-1. It has to be added in Key
|
||||||
|
* characteristics. Otherwise, crypto operations will fail with Incompatible
|
||||||
|
* MGF1 digest.
|
||||||
|
*/
|
||||||
|
if (!hasDefaultMgf1DigestBeenAdded[0]) {
|
||||||
|
params.add(KeyStore2ParameterUtils.makeEnum(
|
||||||
|
KeymasterDefs.KM_TAG_RSA_OAEP_MGF_DIGEST,
|
||||||
|
KeyProperties.Digest.toKeymaster(DEFAULT_MGF1_DIGEST)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
ArrayUtils.forEach(mKeymasterSignaturePaddings, (padding) -> {
|
ArrayUtils.forEach(mKeymasterSignaturePaddings, (padding) -> {
|
||||||
params.add(KeyStore2ParameterUtils.makeEnum(
|
params.add(KeyStore2ParameterUtils.makeEnum(
|
||||||
|
|||||||
@@ -161,10 +161,11 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase
|
|||||||
*/
|
*/
|
||||||
abstract static class OAEPWithMGF1Padding extends AndroidKeyStoreRSACipherSpi {
|
abstract static class OAEPWithMGF1Padding extends AndroidKeyStoreRSACipherSpi {
|
||||||
|
|
||||||
private static final String MGF_ALGORITGM_MGF1 = "MGF1";
|
private static final String MGF_ALGORITHM_MGF1 = "MGF1";
|
||||||
|
|
||||||
private int mKeymasterDigest = -1;
|
private int mKeymasterDigest = -1;
|
||||||
private int mDigestOutputSizeBytes;
|
private int mDigestOutputSizeBytes;
|
||||||
|
private int mKeymasterMgf1Digest = KeymasterDefs.KM_DIGEST_SHA1; // Default MGF1 digest
|
||||||
|
|
||||||
OAEPWithMGF1Padding(int keymasterDigest) {
|
OAEPWithMGF1Padding(int keymasterDigest) {
|
||||||
super(KeymasterDefs.KM_PAD_RSA_OAEP);
|
super(KeymasterDefs.KM_PAD_RSA_OAEP);
|
||||||
@@ -189,10 +190,10 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase
|
|||||||
+ ". Only OAEPParameterSpec supported");
|
+ ". Only OAEPParameterSpec supported");
|
||||||
}
|
}
|
||||||
OAEPParameterSpec spec = (OAEPParameterSpec) params;
|
OAEPParameterSpec spec = (OAEPParameterSpec) params;
|
||||||
if (!MGF_ALGORITGM_MGF1.equalsIgnoreCase(spec.getMGFAlgorithm())) {
|
if (!MGF_ALGORITHM_MGF1.equalsIgnoreCase(spec.getMGFAlgorithm())) {
|
||||||
throw new InvalidAlgorithmParameterException(
|
throw new InvalidAlgorithmParameterException(
|
||||||
"Unsupported MGF: " + spec.getMGFAlgorithm()
|
"Unsupported MGF: " + spec.getMGFAlgorithm()
|
||||||
+ ". Only " + MGF_ALGORITGM_MGF1 + " supported");
|
+ ". Only " + MGF_ALGORITHM_MGF1 + " supported");
|
||||||
}
|
}
|
||||||
String jcaDigest = spec.getDigestAlgorithm();
|
String jcaDigest = spec.getDigestAlgorithm();
|
||||||
int keymasterDigest;
|
int keymasterDigest;
|
||||||
@@ -225,11 +226,6 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase
|
|||||||
}
|
}
|
||||||
MGF1ParameterSpec mgfSpec = (MGF1ParameterSpec) mgfParams;
|
MGF1ParameterSpec mgfSpec = (MGF1ParameterSpec) mgfParams;
|
||||||
String mgf1JcaDigest = mgfSpec.getDigestAlgorithm();
|
String mgf1JcaDigest = mgfSpec.getDigestAlgorithm();
|
||||||
if (!KeyProperties.DIGEST_SHA1.equalsIgnoreCase(mgf1JcaDigest)) {
|
|
||||||
throw new InvalidAlgorithmParameterException(
|
|
||||||
"Unsupported MGF1 digest: " + mgf1JcaDigest
|
|
||||||
+ ". Only " + KeyProperties.DIGEST_SHA1 + " supported");
|
|
||||||
}
|
|
||||||
PSource pSource = spec.getPSource();
|
PSource pSource = spec.getPSource();
|
||||||
if (!(pSource instanceof PSource.PSpecified)) {
|
if (!(pSource instanceof PSource.PSpecified)) {
|
||||||
throw new InvalidAlgorithmParameterException(
|
throw new InvalidAlgorithmParameterException(
|
||||||
@@ -244,6 +240,7 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase
|
|||||||
+ ". Only pSpecifiedEmpty (PSource.PSpecified.DEFAULT) supported");
|
+ ". Only pSpecifiedEmpty (PSource.PSpecified.DEFAULT) supported");
|
||||||
}
|
}
|
||||||
mKeymasterDigest = keymasterDigest;
|
mKeymasterDigest = keymasterDigest;
|
||||||
|
mKeymasterMgf1Digest = KeyProperties.Digest.toKeymaster(mgf1JcaDigest);
|
||||||
mDigestOutputSizeBytes =
|
mDigestOutputSizeBytes =
|
||||||
(KeymasterUtils.getDigestOutputSizeBits(keymasterDigest) + 7) / 8;
|
(KeymasterUtils.getDigestOutputSizeBits(keymasterDigest) + 7) / 8;
|
||||||
}
|
}
|
||||||
@@ -274,8 +271,8 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase
|
|||||||
OAEPParameterSpec spec =
|
OAEPParameterSpec spec =
|
||||||
new OAEPParameterSpec(
|
new OAEPParameterSpec(
|
||||||
KeyProperties.Digest.fromKeymaster(mKeymasterDigest),
|
KeyProperties.Digest.fromKeymaster(mKeymasterDigest),
|
||||||
MGF_ALGORITGM_MGF1,
|
MGF_ALGORITHM_MGF1,
|
||||||
MGF1ParameterSpec.SHA1,
|
KeyProperties.Digest.fromKeymasterToMGF1ParameterSpec(mKeymasterMgf1Digest),
|
||||||
PSource.PSpecified.DEFAULT);
|
PSource.PSpecified.DEFAULT);
|
||||||
try {
|
try {
|
||||||
AlgorithmParameters params = AlgorithmParameters.getInstance("OAEP");
|
AlgorithmParameters params = AlgorithmParameters.getInstance("OAEP");
|
||||||
@@ -298,6 +295,9 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase
|
|||||||
parameters.add(KeyStore2ParameterUtils.makeEnum(
|
parameters.add(KeyStore2ParameterUtils.makeEnum(
|
||||||
KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigest
|
KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigest
|
||||||
));
|
));
|
||||||
|
parameters.add(KeyStore2ParameterUtils.makeEnum(
|
||||||
|
KeymasterDefs.KM_TAG_RSA_OAEP_MGF_DIGEST, mKeymasterMgf1Digest
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package android.security.keystore2;
|
package android.security.keystore2;
|
||||||
|
|
||||||
|
import static android.security.keystore2.AndroidKeyStoreCipherSpiBase.DEFAULT_MGF1_DIGEST;
|
||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.hardware.biometrics.BiometricManager;
|
import android.hardware.biometrics.BiometricManager;
|
||||||
import android.hardware.security.keymint.HardwareAuthenticatorType;
|
import android.hardware.security.keymint.HardwareAuthenticatorType;
|
||||||
@@ -511,6 +513,28 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
|
|||||||
KeymasterDefs.KM_TAG_PADDING,
|
KeymasterDefs.KM_TAG_PADDING,
|
||||||
padding
|
padding
|
||||||
));
|
));
|
||||||
|
if (padding == KeymasterDefs.KM_PAD_RSA_OAEP) {
|
||||||
|
if (spec.isDigestsSpecified()) {
|
||||||
|
boolean hasDefaultMgf1DigestBeenAdded = false;
|
||||||
|
for (String digest : spec.getDigests()) {
|
||||||
|
importArgs.add(KeyStore2ParameterUtils.makeEnum(
|
||||||
|
KeymasterDefs.KM_TAG_RSA_OAEP_MGF_DIGEST,
|
||||||
|
KeyProperties.Digest.toKeymaster(digest)
|
||||||
|
));
|
||||||
|
hasDefaultMgf1DigestBeenAdded |= digest.equals(DEFAULT_MGF1_DIGEST);
|
||||||
|
}
|
||||||
|
/* Because of default MGF1 digest is SHA-1. It has to be added in Key
|
||||||
|
* characteristics. Otherwise, crypto operations will fail with Incompatible
|
||||||
|
* MGF1 digest.
|
||||||
|
*/
|
||||||
|
if (!hasDefaultMgf1DigestBeenAdded) {
|
||||||
|
importArgs.add(KeyStore2ParameterUtils.makeEnum(
|
||||||
|
KeymasterDefs.KM_TAG_RSA_OAEP_MGF_DIGEST,
|
||||||
|
KeyProperties.Digest.toKeymaster(DEFAULT_MGF1_DIGEST)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for (String padding : spec.getSignaturePaddings()) {
|
for (String padding : spec.getSignaturePaddings()) {
|
||||||
importArgs.add(KeyStore2ParameterUtils.makeEnum(
|
importArgs.add(KeyStore2ParameterUtils.makeEnum(
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ public abstract class KeyStore2ParameterUtils {
|
|||||||
kp.value = KeyParameterValue.blockMode(v);
|
kp.value = KeyParameterValue.blockMode(v);
|
||||||
break;
|
break;
|
||||||
case Tag.DIGEST:
|
case Tag.DIGEST:
|
||||||
|
case Tag.RSA_OAEP_MGF_DIGEST:
|
||||||
kp.value = KeyParameterValue.digest(v);
|
kp.value = KeyParameterValue.digest(v);
|
||||||
break;
|
break;
|
||||||
case Tag.EC_CURVE:
|
case Tag.EC_CURVE:
|
||||||
|
|||||||
Reference in New Issue
Block a user