Use StrongBox on API 28+ if available.

This commit is contained in:
akwizgran
2020-01-09 15:18:58 +00:00
parent fc6b596241
commit f76d08c19a
3 changed files with 45 additions and 12 deletions

View File

@@ -3,6 +3,7 @@ package org.briarproject.bramble.api.crypto;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.security.spec.AlgorithmParameterSpec; import java.security.spec.AlgorithmParameterSpec;
import java.util.List;
/** /**
* Configures the use of a stored key to strengthen password-based encryption. * Configures the use of a stored key to strengthen password-based encryption.
@@ -23,5 +24,9 @@ public interface KeyStoreConfig {
String getMacAlgorithmName(); String getMacAlgorithmName();
AlgorithmParameterSpec getParameterSpec(); /**
* Returns a list of {@link AlgorithmParameterSpec AlgorithmParameterSpecs}
* to use for key generation, in order of preference.
*/
List<AlgorithmParameterSpec> getParameterSpecs();
} }

View File

@@ -34,6 +34,7 @@ import java.security.NoSuchAlgorithmException;
import java.security.Provider; import java.security.Provider;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.security.Security; import java.security.Security;
import java.security.spec.AlgorithmParameterSpec;
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@@ -382,17 +383,28 @@ class CryptoComponentImpl implements CryptoComponent {
KeyStore ks = KeyStore.getInstance(config.getKeyStoreType()); KeyStore ks = KeyStore.getInstance(config.getKeyStoreType());
ks.load(null); ks.load(null);
// Load or generate the stored key // Load or generate the stored key
javax.crypto.SecretKey storedKey; javax.crypto.SecretKey storedKey = null;
Entry e = ks.getEntry(config.getKeyAlias(), null); Entry e = ks.getEntry(config.getKeyAlias(), null);
if (e == null) { if (e == null) {
if (!generateIfMissing) { if (!generateIfMissing) {
LOG.warning("Key not found in keystore"); LOG.warning("Key not found in keystore");
return null; return null;
} }
KeyGenerator kg = KeyGenerator.getInstance( // Try the parameter specs in order of preference
config.getMacAlgorithmName(), config.getProviderName()); for (AlgorithmParameterSpec spec : config.getParameterSpecs()) {
kg.init(config.getParameterSpec()); try {
storedKey = kg.generateKey(); KeyGenerator kg = KeyGenerator.getInstance(
config.getMacAlgorithmName(),
config.getProviderName());
kg.init(spec);
storedKey = kg.generateKey();
} catch (GeneralSecurityException e1) {
if (LOG.isLoggable(INFO))
LOG.info("Could not generate key: " + e1);
// Fall back to next spec
}
}
if (storedKey == null) throw new IllegalArgumentException();
LOG.info("Stored key in keystore"); LOG.info("Stored key in keystore");
} else { } else {
if (!(e instanceof SecretKeyEntry)) if (!(e instanceof SecretKeyEntry))

View File

@@ -6,21 +6,37 @@ import org.briarproject.bramble.api.crypto.KeyStoreConfig;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.security.spec.AlgorithmParameterSpec; import java.security.spec.AlgorithmParameterSpec;
import java.util.List;
import androidx.annotation.RequiresApi; import androidx.annotation.RequiresApi;
import static android.os.Build.VERSION.SDK_INT;
import static android.security.keystore.KeyProperties.PURPOSE_SIGN; import static android.security.keystore.KeyProperties.PURPOSE_SIGN;
import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
@RequiresApi(23) @RequiresApi(23)
@NotNullByDefault @NotNullByDefault
class AndroidKeyStoreConfig implements KeyStoreConfig { class AndroidKeyStoreConfig implements KeyStoreConfig {
private final KeyGenParameterSpec spec; private final List<AlgorithmParameterSpec> specs;
AndroidKeyStoreConfig() { AndroidKeyStoreConfig() {
spec = new KeyGenParameterSpec.Builder("db", PURPOSE_SIGN) KeyGenParameterSpec noStrongBox =
.setKeySize(256) new KeyGenParameterSpec.Builder("db", PURPOSE_SIGN)
.build(); .setKeySize(256)
.build();
if (SDK_INT >= 28) {
// Prefer StrongBox if available
KeyGenParameterSpec strongBox =
new KeyGenParameterSpec.Builder("db", PURPOSE_SIGN)
.setIsStrongBoxBacked(true)
.setKeySize(256)
.build();
specs = asList(strongBox, noStrongBox);
} else {
specs = singletonList(noStrongBox);
}
} }
@Override @Override
@@ -44,7 +60,7 @@ class AndroidKeyStoreConfig implements KeyStoreConfig {
} }
@Override @Override
public AlgorithmParameterSpec getParameterSpec() { public List<AlgorithmParameterSpec> getParameterSpecs() {
return spec; return specs;
} }
} }