I'm trying to get 3DES decryption with the key stores in secure hardware on Android (Trusted Exceution Environment or StrongBox) working.
From what I've read 3DES should be available with KeyMaster 4.0 [1, 2], but I get a NullPointerException: Attempt to get length of null array
in the BC provider with the code below on cipher.init
(see stacktrace at the end). I've tested on Samsung Tab Active 3, Note 10 and S22+, which all seem to support KeyMaster 4 or better (tested through public key attestation).
I've tried explicitly setting a provider, but haven't found any other that implements 3DES decryption. I'm guessing that the NPE from BC means that BC hasn't got access to the key data, which again means that it's not running in the TEE.
I've tried similar code with AES, and it works with the key in hardware-backed store without selecting a provider.
Does anyone have any tips for getting 3DES in KeyMaster working, or are the claims for 3DES support exaggerated?
Test code:
// Load key store
keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
// Generate random 3DES key
KeyGenerator keyGenerator = KeyGenerator.getInstance("DESede");
keyGenerator.init(168);
SecretKey randomDes = keyGenerator.generateKey();
// Store in keystore
keyStore.setEntry(
"randomDes",
new KeyStore.SecretKeyEntry(randomDes),
new KeyProtection.Builder(KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_CBC)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
.build());
// Read key back from keystore, key data is not in object as it is protected
keyStore3Des = (SecretKey) keyStore.getKey("randomDes", null);
assert keyStore3Des.getEncoded() == null;
// Create cipher for decrypt
Cipher cipher = Cipher.getInstance("DESede/CBC/NoPadding");
IvParameterSpec iv = new IvParameterSpec(new byte[8]);
cipher.init(Cipher.DECRYPT_MODE, keyStore3Des, iv);
Stacktrace:
java.lang.NullPointerException: Attempt to get length of null array
at com.android.org.bouncycastle.crypto.params.KeyParameter.<init>(KeyParameter.java:17)
at com.android.org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher.engineInit(BaseBlockCipher.java:787)
at javax.crypto.Cipher.tryTransformWithProvider(Cipher.java:2980)
at javax.crypto.Cipher.tryCombinations(Cipher.java:2891)
at javax.crypto.Cipher$SpiAndProviderUpdater.updateAndGetSpiAndProvider(Cipher.java:2796)
at javax.crypto.Cipher.chooseProvider(Cipher.java:773)
at javax.crypto.Cipher.init(Cipher.java:1288)
at javax.crypto.Cipher.init(Cipher.java:1223)