From 8f94ce2b6657ec7a6ba4efceeaf4548cc99f8d1b Mon Sep 17 00:00:00 2001 From: Jon Markoff Date: Wed, 22 Jul 2020 14:55:13 -0700 Subject: [PATCH 1/6] Added support for NIAPSEC updates, which includes testing devices without biometric hardware. --- .../niap/EncryptedDataService.java | 16 +- .../niap/EncryptionManager.java | 33 ++-- .../certifications/niap/MainActivity.java | 50 ++++-- .../tests/SDPDeviceCredentialTestWorker.java | 170 ++++++++++++++++++ .../niap/tests/SDPTestWorker.java | 65 +++---- .../app/src/main/res/layout/content_main.xml | 12 ++ 6 files changed, 276 insertions(+), 70 deletions(-) create mode 100644 niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/tests/SDPDeviceCredentialTestWorker.java diff --git a/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/EncryptedDataService.java b/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/EncryptedDataService.java index 58257eb6..45eac42b 100644 --- a/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/EncryptedDataService.java +++ b/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/EncryptedDataService.java @@ -26,6 +26,7 @@ import android.os.Build; import android.util.Log; +import com.android.certifications.niap.niapsec.SecureConfig; import com.android.certifications.niap.niapsec.biometric.BiometricSupport; import com.android.certifications.niap.niapsec.biometric.BiometricSupportImpl; import com.android.certifications.niap.niapsec.crypto.SecureCipher; @@ -73,7 +74,7 @@ public void onCreate() { super.onCreate(); this.viewModel = MainActivity.viewModel; biometricSupport = new BiometricSupportImpl(MainActivity.thisActivity, - getApplicationContext()) { + getApplicationContext(), false) { @Override public void onAuthenticationSucceeded() { showMessage(BIOMETRIC_AUTH + " Succeeded!"); @@ -84,17 +85,15 @@ public void onAuthenticationFailed() { onMessage(BIOMETRIC_AUTH + " Failed"); } - @Override - public void onAuthenticationCancelled() { - showMessage(BIOMETRIC_AUTH + " Cancelled!"); - } - @Override public void onMessage(String message) { showMessage(message); } }; - dataManager = new EncryptionManager(getApplicationContext(), biometricSupport); + dataManager = new EncryptionManager(getApplicationContext(), + SecureConfig.getStrongConfig(), + biometricSupport); + deviceLocked = dataManager.deviceLocked(); } @@ -147,7 +146,8 @@ private void createKeys(String fileName) { asymmetricKeyPairAlias, testDataString.getBytes(), (byte[] encryptedData) -> { - SecureCipher secureCipher = SecureCipher.getDefault(biometricSupport); + SecureCipher secureCipher = SecureCipher.getDefault( + SecureConfig.getStrongConfig(biometricSupport)); secureCipher.decryptEncodedData(encryptedData, (byte[] decryptedData) -> { Log.i(TAG, "Decrypted... " + new String(decryptedData)); boolean encrypted = encryptData(fileName, (byte[] cipherText) -> { diff --git a/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/EncryptionManager.java b/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/EncryptionManager.java index d15aca98..a1a50c24 100644 --- a/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/EncryptionManager.java +++ b/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/EncryptionManager.java @@ -22,6 +22,7 @@ import android.util.Log; import android.util.Pair; +import com.android.certifications.niap.niapsec.SecureConfig; import com.android.certifications.niap.niapsec.biometric.BiometricSupport; import com.android.certifications.niap.niapsec.context.SecureContextCompat; import com.android.certifications.niap.niapsec.crypto.EphemeralSecretKey; @@ -43,17 +44,21 @@ public class EncryptionManager { private Context context; private BiometricSupport biometricSupport; + private SecureConfig secureConfig; - public EncryptionManager(Context context, BiometricSupport biometricSupport) { + public EncryptionManager(Context context, + SecureConfig secureConfig, + BiometricSupport biometricSupport) { this.context = context; + this.secureConfig = secureConfig; this.biometricSupport = biometricSupport; } public void createSensitiveDataSymmetricKey(final String keyAlias) { Log.i(TAG, "Generating Key..."); - SecureKeyGenerator keyGenerator = SecureKeyGenerator.getDefault(); + SecureKeyGenerator keyGenerator = SecureKeyGenerator.getInstance(secureConfig); boolean created = keyGenerator.generateKey(keyAlias); - SecureKeyStore secureKeyStore = SecureKeyStore.getDefault(); + SecureKeyStore secureKeyStore = SecureKeyStore.getDefault(secureConfig); final boolean keyInHardware = secureKeyStore.checkKeyInsideSecureHardware(keyAlias); if (UpdateViewModel.updateStatus != null) { UpdateViewModel.updateStatus.postValue("Generated Key Stored in Hardware: " + @@ -63,10 +68,10 @@ public void createSensitiveDataSymmetricKey(final String keyAlias) { public void createSensitiveDataAsymmetricKeyPair(final String keyPairAlias) { Log.i(TAG, "Generating KeyPair (RSA)..."); - SecureKeyGenerator keyGenerator = SecureKeyGenerator.getDefault(); + SecureKeyGenerator keyGenerator = SecureKeyGenerator.getInstance(secureConfig); boolean createdAsym = keyGenerator.generateAsymmetricKeyPair(keyPairAlias); Log.i(TAG, "KeyPair Generated: " + createdAsym); - SecureKeyStore secureKeyStore = SecureKeyStore.getDefault(); + SecureKeyStore secureKeyStore = SecureKeyStore.getDefault(secureConfig); final boolean keyInHardwareAsym = secureKeyStore.checkKeyInsideSecureHardwareAsymmetric(keyPairAlias); if (UpdateViewModel.updateStatus != null) { @@ -76,7 +81,7 @@ public void createSensitiveDataAsymmetricKeyPair(final String keyPairAlias) { } public EphemeralSecretKey createEphemeralKey() { - SecureKeyGenerator secureKeyGenerator = SecureKeyGenerator.getDefault(); + SecureKeyGenerator secureKeyGenerator = SecureKeyGenerator.getInstance(secureConfig); EphemeralSecretKey secretKey = secureKeyGenerator.generateEphemeralDataKey(); Log.i("SDPTestWorker", "Ephemeral AES Key Base64:\n" + Base64.encodeToString(secretKey.getEncoded(), Base64.DEFAULT)); @@ -87,7 +92,7 @@ public void encryptEphemeralKeyAsymmetric( EphemeralSecretKey secretKey, String keyPairAlias, SecureCipher.SecureAsymmetricEncryptionCallback callback) { - SecureCipher secureCipher = SecureCipher.getDefault(biometricSupport); + SecureCipher secureCipher = SecureCipher.getDefault(secureConfig); secureCipher.encryptSensitiveDataAsymmetric(keyPairAlias, secretKey.getEncoded(), callback); } @@ -117,7 +122,7 @@ public void encryptData(String symKeyAlias, // Asymmetric Sensitive Data Protection Log.i(TAG, "Device Locked: Encrypted Data using Asymmetric Key"); EphemeralSecretKey secretKey = createEphemeralKey(); - SecureCipher secureCipher = SecureCipher.getDefault(biometricSupport); + SecureCipher secureCipher = SecureCipher.getDefault(secureConfig); Pair encryptedData = secureCipher.encryptEphemeralData(secretKey, data); encryptEphemeralKeyAsymmetric(secretKey, asymKeyPairAlias, (byte[] encryptedEphemeralKey) -> { @@ -130,7 +135,7 @@ public void encryptData(String symKeyAlias, asymmetricEncryptionCallback.encryptionComplete(encodedData); }); } else { - SecureCipher secureCipher = SecureCipher.getDefault(biometricSupport); + SecureCipher secureCipher = SecureCipher.getDefault(secureConfig); secureCipher.encryptSensitiveData( symKeyAlias, data, @@ -152,7 +157,7 @@ public boolean encryptData(String fileName, String symKeyAlias, final AtomicBoolean saved = new AtomicBoolean(false); encryptData(symKeyAlias, asymKeyPairAlias, data, (byte[] encryptedData) -> { try { - SecureContextCompat secureContext = new SecureContextCompat(context); + SecureContextCompat secureContext = new SecureContextCompat(context, secureConfig); Log.i(TAG, "Keyname " + fileName.substring(0, fileName.indexOf("."))); FileOutputStream outputStream = secureContext.openEncryptedFileOutput( fileName, @@ -177,7 +182,7 @@ public void convertEphemeralEncodedData( byte[] encodedCipherText, SecureCipher.SecureAsymmetricEncryptionCallback callback) { if (!deviceLocked()) { - SecureCipher secureCipher = SecureCipher.getDefault(biometricSupport); + SecureCipher secureCipher = SecureCipher.getDefault(secureConfig); secureCipher.decryptEncodedData( encodedCipherText, (byte[] decryptedData) -> { @@ -198,7 +203,7 @@ public void convertEphemeralEncodedData( public boolean convertEphemeralEncodedData(String fileName, String keyPairAlias) { AtomicBoolean converted = new AtomicBoolean(false); try { - SecureContextCompat secureContext = new SecureContextCompat(context); + SecureContextCompat secureContext = new SecureContextCompat(context, secureConfig); secureContext.openEncryptedFileInput( fileName, Executors.newSingleThreadExecutor(), @@ -240,7 +245,7 @@ public boolean convertEphemeralEncodedData(String fileName, String keyPairAlias) public void decryptData(String fileName, SecureCipher.SecureDecryptionCallback callback) { try { - SecureContextCompat secureContext = new SecureContextCompat(context); + SecureContextCompat secureContext = new SecureContextCompat(context, secureConfig); secureContext.openEncryptedFileInput( fileName, Executors.newSingleThreadExecutor(), @@ -250,7 +255,7 @@ public void decryptData(String fileName, SecureCipher.SecureDecryptionCallback c byte[] encodedData = new byte[inputStream.available()]; inputStream.read(encodedData); inputStream.close(); - SecureCipher secureCipher = SecureCipher.getDefault(biometricSupport); + SecureCipher secureCipher = SecureCipher.getDefault(secureConfig); secureCipher.decryptEncodedData(encodedData, callback); } catch (IOException ex) { Log.e(TAG, "There was a problem writing to file... " + ex.getMessage()); diff --git a/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/MainActivity.java b/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/MainActivity.java index 719b4c05..d26f67d4 100644 --- a/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/MainActivity.java +++ b/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/MainActivity.java @@ -34,6 +34,7 @@ import androidx.lifecycle.Observer; import androidx.lifecycle.ViewModelProviders; import androidx.work.OneTimeWorkRequest; +import androidx.work.WorkContinuation; import androidx.work.WorkManager; import com.android.certifications.niap.niapsec.SecureConfig; @@ -41,6 +42,7 @@ import com.android.certifications.niap.niapsec.crypto.SecureCipher; import com.android.certifications.niap.niapsec.net.SecureURL; import com.android.certifications.niap.niapsecexample.R; +import com.android.certifications.niap.tests.SDPDeviceCredentialTestWorker; import com.google.android.material.floatingactionbutton.FloatingActionButton; import com.google.android.material.snackbar.Snackbar; import com.android.certifications.niap.tests.SDPAuthFailureTestWorker; @@ -69,6 +71,9 @@ public class MainActivity extends FragmentActivity { public static FragmentActivity thisActivity; private TextView textView; private CheckBox runInBackgroundCheckBox; + private CheckBox useDeviceCredentialCheckBox; + private CheckBox testNoAuthCheckBox; + private boolean serviceRunning = false; public static UpdateViewModel viewModel; private BiometricSupport biometricSupport; @@ -81,6 +86,8 @@ protected void onCreate(Bundle savedInstanceState) { thisActivity = this; textView = (TextView) findViewById(R.id.output_textview); runInBackgroundCheckBox = findViewById(R.id.run_in_background); + useDeviceCredentialCheckBox = findViewById(R.id.use_device_credential); + testNoAuthCheckBox = findViewById(R.id.test_failure_sdp); viewModel = ViewModelProviders.of(this).get(UpdateViewModel.class); FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); fab.setOnClickListener(new View.OnClickListener() { @@ -131,16 +138,27 @@ private void runTest() { Log.i(TAG, "!!!!!!!!!!LOCK DEVICE NOW...!!!!"); initialDelay = 6; } - OneTimeWorkRequest sdpTestWorker = new OneTimeWorkRequest.Builder(SDPTestWorker.class) - .setInitialDelay(initialDelay, TimeUnit.SECONDS) - .build(); - OneTimeWorkRequest sdpFailureTestWorker = - new OneTimeWorkRequest.Builder(SDPAuthFailureTestWorker.class) - .build(); - WorkManager.getInstance() - .beginWith(sdpTestWorker) - .then(sdpFailureTestWorker) - .enqueue(); + OneTimeWorkRequest sdpTestWorker; + if(useDeviceCredentialCheckBox.isChecked()) { + sdpTestWorker = new OneTimeWorkRequest.Builder(SDPDeviceCredentialTestWorker.class) + .setInitialDelay(initialDelay, TimeUnit.SECONDS) + .build(); + } else { + sdpTestWorker = new OneTimeWorkRequest.Builder(SDPTestWorker.class) + .setInitialDelay(initialDelay, TimeUnit.SECONDS) + .build(); + } + + WorkContinuation workContinuation = + WorkManager.getInstance(getApplicationContext()).beginWith(sdpTestWorker); + if(testNoAuthCheckBox.isChecked()) { + OneTimeWorkRequest sdpFailureTestWorker = + new OneTimeWorkRequest.Builder(SDPAuthFailureTestWorker.class) + .build(); + workContinuation.then(sdpFailureTestWorker); + } + workContinuation.enqueue(); + try { new AsyncTask() { @@ -172,7 +190,15 @@ private void showMessage(String message) { } private void testOAEP() { - EncryptionManager encryptionManager = new EncryptionManager(this, biometricSupport); + SecureConfig config; + if(useDeviceCredentialCheckBox.isChecked()) { + config = SecureConfig.getStrongDeviceCredentialConfig(biometricSupport); + } else { + config = SecureConfig.getStrongConfig(biometricSupport); + } + EncryptionManager encryptionManager = new EncryptionManager(this, + config, + biometricSupport); Log.i(TAG, "Creating Keypair OAEP_TESTING_RSA"); encryptionManager.createSensitiveDataAsymmetricKeyPair("OAEP_TESTING_RSA"); Log.i(TAG, "Created Keypair OAEP_TESTING_RSA"); @@ -180,7 +206,7 @@ private void testOAEP() { Log.i(TAG, "Encrypting " + new String(clearText)); - SecureCipher secureCipher = SecureCipher.getDefault(biometricSupport); + SecureCipher secureCipher = SecureCipher.getDefault(config); secureCipher.encryptSensitiveDataAsymmetric( "OAEP_TESTING_RSA", clearText, diff --git a/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/tests/SDPDeviceCredentialTestWorker.java b/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/tests/SDPDeviceCredentialTestWorker.java new file mode 100644 index 00000000..986bad9b --- /dev/null +++ b/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/tests/SDPDeviceCredentialTestWorker.java @@ -0,0 +1,170 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.certifications.niap.tests; + +import android.content.Context; + +import com.android.certifications.niap.MainActivity; +import com.android.certifications.niap.TestUtil; +import com.android.certifications.niap.niapsec.SecureConfig; +import com.android.certifications.niap.niapsec.biometric.BiometricSupport; +import com.android.certifications.niap.niapsec.biometric.BiometricSupportImpl; +import com.android.certifications.niap.niapsec.context.SecureContextCompat; +import com.android.certifications.niap.niapsec.crypto.SecureKeyGenerator; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.nio.charset.StandardCharsets; +import java.security.KeyPairGenerator; +import java.util.concurrent.Executors; + +import javax.crypto.Cipher; + +import androidx.annotation.NonNull; +import androidx.work.Worker; +import androidx.work.WorkerParameters; + +/** + * Worker class that runs a test to encrypt and decrypt data with the NIAPSEC library. + *

+ * This test should be successful after running the application. Please note that, this test + * does require that the user authorize using the devices default unlock implementation which can + * be a device pin or password, fingerprint, or face identification. + */ +public class SDPDeviceCredentialTestWorker extends Worker { + + private static final String FILE_NAME = "test_file"; + private static final String KEY_PAIR_ALIAS = "key_pair_alias"; + + public SDPDeviceCredentialTestWorker(Context context, WorkerParameters parameters) { + super(context, parameters); + + try { + new File(getApplicationContext().getFilesDir(), FILE_NAME).delete(); + } catch (Exception ex) { + } + } + + @NonNull + @Override + public Result doWork() { + try { + // Write SDP File + BiometricSupport biometricSupport = new BiometricSupportImpl( + MainActivity.thisActivity, + getApplicationContext(), true) { + @Override + public void onAuthenticationSucceeded() { + TestUtil.logSuccess(getClass(), "SDP Device Credential Unlock " + + "Succeeded, private key available for decryption through the " + + "AndroidKeyStore."); + } + + @Override + public void onAuthenticationFailed() { + TestUtil.logFailure(getClass(), + "SDP Device Credential Unlock failed, " + + "file not available for decryption."); + } + + @Override + public void onMessage(String message) { + TestUtil.logSuccess(getClass(), message); + } + }; + + SecureConfig secureConfig = + SecureConfig.getStrongDeviceCredentialConfig(biometricSupport); + secureConfig.setDebugLoggingEnabled(true); + SecureKeyGenerator keyGenerator = SecureKeyGenerator.getInstance(secureConfig); + TestUtil.logSuccess(getClass(), "Generated RSA with provider AndroidKeyStore.", + KeyPairGenerator.class); + keyGenerator.generateAsymmetricKeyPair(KEY_PAIR_ALIAS); + + SecureContextCompat secureContext = new SecureContextCompat( + getApplicationContext(), + secureConfig); + + TestUtil.logSuccess( + getClass(), + "Opening encrypted stream to SDP " + FILE_NAME, + FileOutputStream.class); + TestUtil.logSuccess( + getClass(), + "Writing Data: " + TestUtil.DATA, + FileOutputStream.class); + FileOutputStream outputStream = secureContext.openEncryptedFileOutput( + FILE_NAME, + Context.MODE_PRIVATE, KEY_PAIR_ALIAS); + TestUtil.logSuccess( + getClass(), + "Writing SDP file encrypted contents to " + FILE_NAME, + Cipher.class); + outputStream.write(TestUtil.DATA.getBytes(StandardCharsets.UTF_8)); + outputStream.flush(); + outputStream.close(); + + + FileInputStream rawInputStream = getApplicationContext().openFileInput(FILE_NAME); + byte[] fileContents = new byte[rawInputStream.available()]; + rawInputStream.read(fileContents); + rawInputStream.close(); + TestUtil.logSuccess(getClass(), "SDP File Contents: " + + new String(fileContents, StandardCharsets.UTF_8), FileInputStream.class); + + + // Read file + secureContext.openEncryptedFileInput( + FILE_NAME, + Executors.newSingleThreadExecutor(), + inputStream -> { + try { + byte[] encodedData = new byte[inputStream.available()]; + TestUtil.logSuccess( + getClass(), + "decrypting " + FILE_NAME + " data ", + Cipher.class); + inputStream.read(encodedData); + inputStream.close(); + String plainText = new String(encodedData, StandardCharsets.UTF_8); + TestUtil.logSuccess(getClass(), "File Contents= " + plainText); + if (TestUtil.DATA.equals(plainText)) { + TestUtil.logSuccess(getClass(), "Data matches..."); + } else { + TestUtil.logFailure(getClass(), "Decryption failed"); + } + + + } catch (Exception ex) { + TestUtil.logFailure( + getClass(), + "Failed on file decryption " + ex.getMessage()); + } + }); + + return Result.success(); + } catch (Exception ex) { + ex.printStackTrace(); + TestUtil.logFailure(getClass(), ex.getMessage()); + } + TestUtil.logFailure(getClass(), "Unknown Error, please check the logs."); + return Result.failure(); + } + + +} diff --git a/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/tests/SDPTestWorker.java b/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/tests/SDPTestWorker.java index b9a71397..b2ae8c19 100644 --- a/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/tests/SDPTestWorker.java +++ b/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/tests/SDPTestWorker.java @@ -41,7 +41,7 @@ /** * Worker class that runs a test to encrypt and decrypt data with the NIAPSEC library. - * + *

* This test should be successful after running the application. Please note that, this test * does require that the user authorize using the devices default unlock implementation which can * be a device pin or password, fingerprint, or face identification. @@ -67,11 +67,11 @@ public Result doWork() { // Write SDP File BiometricSupport biometricSupport = new BiometricSupportImpl( MainActivity.thisActivity, - getApplicationContext()) { + getApplicationContext(), false) { @Override public void onAuthenticationSucceeded() { TestUtil.logSuccess(getClass(), "SDP Biometric Unlock Succeeded, " + - "private key available for decryption through the AndroidKeyStore."); + "private key available for decryption through the AndroidKeyStore."); } @Override @@ -80,26 +80,19 @@ public void onAuthenticationFailed() { "file not available for decryption."); } - @Override - public void onAuthenticationCancelled() { - TestUtil.logFailure(getClass(), "SDP Biometric Unlock cancelled, " + - "file not available for decryption."); - } - @Override public void onMessage(String message) { TestUtil.logSuccess(getClass(), message); } }; - SecureKeyGenerator keyGenerator = SecureKeyGenerator.getInstance(SecureConfig. - getStrongConfig(biometricSupport)); + SecureConfig secureConfig = SecureConfig.getStrongConfig(biometricSupport); + secureConfig.setDebugLoggingEnabled(true); + SecureKeyGenerator keyGenerator = SecureKeyGenerator.getInstance(secureConfig); TestUtil.logSuccess(getClass(), "Generated RSA with provider AndroidKeyStore.", KeyPairGenerator.class); keyGenerator.generateAsymmetricKeyPair(KEY_PAIR_ALIAS); - SecureConfig secureConfig = SecureConfig.getStrongConfig(biometricSupport); - secureConfig.setDebugLoggingEnabled(true); SecureContextCompat secureContext = new SecureContextCompat( getApplicationContext(), secureConfig); @@ -137,29 +130,29 @@ public void onMessage(String message) { FILE_NAME, Executors.newSingleThreadExecutor(), inputStream -> { - try { - byte[] encodedData = new byte[inputStream.available()]; - TestUtil.logSuccess( - getClass(), - "decrypting " + FILE_NAME + " data ", - Cipher.class); - inputStream.read(encodedData); - inputStream.close(); - String plainText = new String(encodedData, StandardCharsets.UTF_8); - TestUtil.logSuccess(getClass(), "File Contents= " + plainText); - if(TestUtil.DATA.equals(plainText)) { - TestUtil.logSuccess(getClass(), "Data matches..."); - } else { - TestUtil.logFailure(getClass(), "Decryption failed"); - } - - - } catch (Exception ex) { - TestUtil.logFailure( - getClass(), - "Failed on file decryption " + ex.getMessage()); - } - }); + try { + byte[] encodedData = new byte[inputStream.available()]; + TestUtil.logSuccess( + getClass(), + "decrypting " + FILE_NAME + " data ", + Cipher.class); + inputStream.read(encodedData); + inputStream.close(); + String plainText = new String(encodedData, StandardCharsets.UTF_8); + TestUtil.logSuccess(getClass(), "File Contents= " + plainText); + if (TestUtil.DATA.equals(plainText)) { + TestUtil.logSuccess(getClass(), "Data matches..."); + } else { + TestUtil.logFailure(getClass(), "Decryption failed"); + } + + + } catch (Exception ex) { + TestUtil.logFailure( + getClass(), + "Failed on file decryption " + ex.getMessage()); + } + }); return Result.success(); } catch (Exception ex) { diff --git a/niap-cc/NIAPSecExample/app/src/main/res/layout/content_main.xml b/niap-cc/NIAPSecExample/app/src/main/res/layout/content_main.xml index 86a04c4a..258ecf98 100644 --- a/niap-cc/NIAPSecExample/app/src/main/res/layout/content_main.xml +++ b/niap-cc/NIAPSecExample/app/src/main/res/layout/content_main.xml @@ -55,6 +55,18 @@ android:layout_height="wrap_content" android:text="Delay Start for 5 seconds"/> + + + + Date: Fri, 7 Aug 2020 12:03:00 -0700 Subject: [PATCH 2/6] Add key testing patches for Android 9 --- ...ging-for-SP800-derived-passwords-too.patch | 37 +++++++ ...-NOT-SUBMIT-log-disk-encryption-keys.patch | 30 ++++++ ...-DO-NOT-SUBMIT-log-personalized-keys.patch | 96 +++++++++++++++++++ ...p-master-key-when-generated-and-read.patch | 72 ++++++++++++++ .../Android9/0001-Dump-security-key.patch | 30 ++++++ ...Dump-synthetic-password-related-keys.patch | 52 ++++++++++ niap-cc/KeyTestingPatches/Android9/README.md | 16 ++++ 7 files changed, 333 insertions(+) create mode 100644 niap-cc/KeyTestingPatches/Android9/0001-Add-logging-for-SP800-derived-passwords-too.patch create mode 100644 niap-cc/KeyTestingPatches/Android9/0001-DO-NOT-SUBMIT-log-disk-encryption-keys.patch create mode 100644 niap-cc/KeyTestingPatches/Android9/0001-DO-NOT-SUBMIT-log-personalized-keys.patch create mode 100644 niap-cc/KeyTestingPatches/Android9/0001-Dump-master-key-when-generated-and-read.patch create mode 100644 niap-cc/KeyTestingPatches/Android9/0001-Dump-security-key.patch create mode 100644 niap-cc/KeyTestingPatches/Android9/0001-Dump-synthetic-password-related-keys.patch create mode 100644 niap-cc/KeyTestingPatches/Android9/README.md diff --git a/niap-cc/KeyTestingPatches/Android9/0001-Add-logging-for-SP800-derived-passwords-too.patch b/niap-cc/KeyTestingPatches/Android9/0001-Add-logging-for-SP800-derived-passwords-too.patch new file mode 100644 index 00000000..015a8880 --- /dev/null +++ b/niap-cc/KeyTestingPatches/Android9/0001-Add-logging-for-SP800-derived-passwords-too.patch @@ -0,0 +1,37 @@ +From 56b31560245ce5c17a3cc4c0c80eeb33840664a2 Mon Sep 17 00:00:00 2001 +From: Paul Crowley +Date: Thu, 6 Aug 2020 22:54:29 -0700 +Subject: [PATCH] Add logging for SP800-derived passwords too + +Change-Id: Icc8ffdfaed260034bfd5e911b6621c7981918419 +--- + .../locksettings/SyntheticPasswordManager.java | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java +index 3c6362000eb..b62843e0a85 100644 +--- a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java ++++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java +@@ -156,8 +156,18 @@ public class SyntheticPasswordManager { + + private byte[] derivePassword(byte[] personalization) { + if (mVersion == SYNTHETIC_PASSWORD_VERSION_V3) { +- return (new SP800Derive(syntheticPassword.getBytes())) ++ StringBuilder logMessage = new StringBuilder(); ++ logMessage.append("DO NOT SUBMIT derivePassword"); ++ logMessage.append(" personalization: "); ++ logMessage.append(personalization); ++ logMessage.append(" context: "); ++ logMessage.append(SyntheticPasswordCrypto.bytesToHex(PERSONALISATION_CONTEXT)); ++ byte[] res = (new SP800Derive(syntheticPassword.getBytes())) + .withContext(personalization, PERSONALISATION_CONTEXT); ++ logMessage.append(" result: "); ++ logMessage.append(SyntheticPasswordCrypto.bytesToHex(res)); ++ Log.e(TAG, logMessage.toString()); ++ return res; + } else { + return SyntheticPasswordCrypto.personalisedHash(personalization, + syntheticPassword.getBytes()); +-- +2.28.0.236.gb10cc79966-goog + diff --git a/niap-cc/KeyTestingPatches/Android9/0001-DO-NOT-SUBMIT-log-disk-encryption-keys.patch b/niap-cc/KeyTestingPatches/Android9/0001-DO-NOT-SUBMIT-log-disk-encryption-keys.patch new file mode 100644 index 00000000..789c539e --- /dev/null +++ b/niap-cc/KeyTestingPatches/Android9/0001-DO-NOT-SUBMIT-log-disk-encryption-keys.patch @@ -0,0 +1,30 @@ +From 66686d09a7a3b37aab7a3fbf789d0d47724d6d7f Mon Sep 17 00:00:00 2001 +From: Paul Crowley +Date: Thu, 24 Jan 2019 11:23:50 +0000 +Subject: [PATCH] DO NOT SUBMIT log disk encryption keys + +Bug: 121287968 +Test: DO NOT SUBMIT +Change-Id: I1232ca6aff48b858e6e9fbbda70e96b2f80987a7 +--- + KeyStorage.cpp | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/KeyStorage.cpp b/KeyStorage.cpp +index 0518930..47854af 100644 +--- a/KeyStorage.cpp ++++ b/KeyStorage.cpp +@@ -532,6 +532,10 @@ bool retrieveKey(const std::string& dir, const KeyAuthentication& auth, KeyBuffe + } else { + if (!decryptWithoutKeymaster(appId, encryptedMessage, key)) return false; + } ++ KeyBuffer hexKey; ++ StrToHex(*key, hexKey); ++ hexKey.push_back('\0'); ++ LOG(DEBUG) << "DO NOT SUBMIT log of key in " << dir << " " << hexKey.data(); + return true; + } + +-- +2.28.0.236.gb10cc79966-goog + diff --git a/niap-cc/KeyTestingPatches/Android9/0001-DO-NOT-SUBMIT-log-personalized-keys.patch b/niap-cc/KeyTestingPatches/Android9/0001-DO-NOT-SUBMIT-log-personalized-keys.patch new file mode 100644 index 00000000..f142ee98 --- /dev/null +++ b/niap-cc/KeyTestingPatches/Android9/0001-DO-NOT-SUBMIT-log-personalized-keys.patch @@ -0,0 +1,96 @@ +From cbd836f3221baf246b98345783bda3bcd63b3bd5 Mon Sep 17 00:00:00 2001 +From: Paul Crowley +Date: Fri, 7 Aug 2020 09:57:04 -0700 +Subject: [PATCH] DO NOT SUBMIT log personalized keys + +Change-Id: I20c2f40a2b666bd4795345fa720eac9975fa4f7f +--- + .../locksettings/SyntheticPasswordCrypto.java | 42 ++++++++++++++++++- + 1 file changed, 41 insertions(+), 1 deletion(-) + +diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordCrypto.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordCrypto.java +index ef94000d3a6..1de6d90543b 100644 +--- a/services/core/java/com/android/server/locksettings/SyntheticPasswordCrypto.java ++++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordCrypto.java +@@ -19,8 +19,10 @@ package com.android.server.locksettings; + import android.security.keystore.KeyProperties; + import android.security.keystore.KeyProtection; + ++import android.util.Log; + import java.io.ByteArrayOutputStream; + import java.io.IOException; ++import java.io.UnsupportedEncodingException; + import java.security.InvalidAlgorithmParameterException; + import java.security.InvalidKeyException; + import java.security.KeyStore; +@@ -42,6 +44,7 @@ import javax.crypto.spec.GCMParameterSpec; + import javax.crypto.spec.SecretKeySpec; + + public class SyntheticPasswordCrypto { ++ private static final String TAG = "SyntheticPasswordCrypto"; + private static final int PROFILE_KEY_IV_SIZE = 12; + private static final int AES_KEY_LENGTH = 32; // 256-bit AES key + private static final byte[] APPLICATION_ID_PERSONALIZATION = "application-id".getBytes(); +@@ -189,6 +192,8 @@ public class SyntheticPasswordCrypto { + + protected static byte[] personalisedHash(byte[] personalisation, byte[]... message) { + try { ++ StringBuilder logMessage = new StringBuilder(); ++ logMessage.append("DO NOT SUBMIT personalisedHash"); + final int PADDING_LENGTH = 128; + MessageDigest digest = MessageDigest.getInstance("SHA-512"); + if (personalisation.length > PADDING_LENGTH) { +@@ -196,14 +201,49 @@ public class SyntheticPasswordCrypto { + } + // Personalize the hash + // Pad it to the block size of the hash function ++ logMessage.append(" personalization: "); ++ logMessage.append(bytesToHex(personalisation)); + personalisation = Arrays.copyOf(personalisation, PADDING_LENGTH); + digest.update(personalisation); ++ logMessage.append(" message: ["); + for (byte[] data : message) { ++ logMessage.append(" "); ++ logMessage.append(bytesToHex(data)); + digest.update(data); + } +- return digest.digest(); ++ logMessage.append(" ]"); ++ byte[] res = digest.digest(); ++ logMessage.append(" digest: "); ++ logMessage.append(bytesToHex(res)); ++ Log.e(TAG, logMessage.toString()); ++ return res; + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException("NoSuchAlgorithmException for SHA-512", e); + } + } ++ ++ /** ++ * Uppercase hex string for byte array ++ */ ++ public static String bytesToHex(byte[] bytes) { ++ try { ++ return new String(bytesToHexBytes(bytes), "UTF-8"); ++ } catch (UnsupportedEncodingException e) { ++ throw new RuntimeException(e); ++ } ++ } ++ ++ protected static final byte[] HEX_ARRAY = "0123456789ABCDEF".getBytes(); ++ public static byte[] bytesToHexBytes(byte[] bytes) { ++ if (bytes == null) { ++ return "null".getBytes(); ++ } ++ byte[] hexBytes = new byte[bytes.length * 2]; ++ for ( int j = 0; j < bytes.length; j++ ) { ++ int v = bytes[j] & 0xFF; ++ hexBytes[j * 2] = HEX_ARRAY[v >>> 4]; ++ hexBytes[j * 2 + 1] = HEX_ARRAY[v & 0x0F]; ++ } ++ return hexBytes; ++ } + } +-- +2.28.0.236.gb10cc79966-goog + diff --git a/niap-cc/KeyTestingPatches/Android9/0001-Dump-master-key-when-generated-and-read.patch b/niap-cc/KeyTestingPatches/Android9/0001-Dump-master-key-when-generated-and-read.patch new file mode 100644 index 00000000..d5852417 --- /dev/null +++ b/niap-cc/KeyTestingPatches/Android9/0001-Dump-master-key-when-generated-and-read.patch @@ -0,0 +1,72 @@ +From 7a28909f0343b8b3452ead03901de98c0f35ed72 Mon Sep 17 00:00:00 2001 +From: Branden Archer +Date: Fri, 7 Aug 2020 12:01:04 -0700 +Subject: [PATCH] Dump master key when generated and read + +Change-Id: Ie06f47ebb3155a995a291286d559ca9979a4e4ac +--- + keystore/user_state.cpp | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +diff --git a/keystore/user_state.cpp b/keystore/user_state.cpp +index aab6175..d90aeeb 100644 +--- a/keystore/user_state.cpp ++++ b/keystore/user_state.cpp +@@ -20,6 +20,8 @@ + + #include + #include ++#include ++#include + #include + #include + #include +@@ -140,6 +142,18 @@ ResponseCode UserState::writeMasterKey(const android::String8& pw) { + return masterKeyBlob.writeBlob(mMasterKeyFile, passwordKey, STATE_NO_ERROR); + } + ++static std::string hexEncode(const std::vector& input) { ++ std::stringstream hexStream; ++ for (std::vector::const_iterator it = input.begin(); it != input.end(); ++it) { ++ char raw[20] = {0}; ++ snprintf(raw, sizeof(raw), "%02x", *it); ++ hexStream << raw; ++ } ++ std::string result; ++ hexStream >> result; ++ return result; ++} ++ + ResponseCode UserState::readMasterKey(const android::String8& pw) { + int in = TEMP_FAILURE_RETRY(open(mMasterKeyFile, O_RDONLY)); + if (in < 0) { +@@ -187,6 +201,8 @@ ResponseCode UserState::readMasterKey(const android::String8& pw) { + if (response == ResponseCode::NO_ERROR) { + mMasterKey = std::vector(masterKeyBlob.getValue(), + masterKeyBlob.getValue() + masterKeyBlob.getLength()); ++ std::string hexKeyBlob = hexEncode(mMasterKey); ++ ALOGI("CKM.4 keystore daemon Master key read: %s %lu", hexKeyBlob.c_str(), mMasterKey.size()); + setupMasterKeys(); + } + return response; +@@ -255,6 +271,8 @@ void UserState::generateKeyFromPassword(std::vector& key, const android + + PKCS5_PBKDF2_HMAC(reinterpret_cast(pw.string()), pw.length(), salt, saltSize, 8192, + digest, key.size(), key.data()); ++ std::string hexKey = hexEncode(key); ++ ALOGI("CKM.4 keystore daemon Password key: %s", hexKey.c_str()); + } + + bool UserState::generateSalt() { +@@ -269,6 +287,8 @@ bool UserState::generateMasterKey() { + if (!generateSalt()) { + return false; + } ++ std::string hexKey = hexEncode(mMasterKey); ++ ALOGI("CKM.4 keystore daemon Master key generate: %s %lu", hexKey.c_str(), mMasterKey.size()); + return true; + } + +-- +2.28.0.236.gb10cc79966-goog + diff --git a/niap-cc/KeyTestingPatches/Android9/0001-Dump-security-key.patch b/niap-cc/KeyTestingPatches/Android9/0001-Dump-security-key.patch new file mode 100644 index 00000000..1a355def --- /dev/null +++ b/niap-cc/KeyTestingPatches/Android9/0001-Dump-security-key.patch @@ -0,0 +1,30 @@ +From 5c72e383be28b5644e7b89833e0afe53095a6bc8 Mon Sep 17 00:00:00 2001 +From: Sunil Ravi +Date: Sun, 10 Mar 2019 12:49:53 -0700 +Subject: [PATCH] Dump security key + +Dump security keys from supplicant + +Bug: 123907624 +Test: Regression test +Change-Id: I77254d92077d20d6a9520d7cf9f55eecbb2853f6 +--- + src/utils/wpa_debug.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/utils/wpa_debug.c b/src/utils/wpa_debug.c +index c437000..916e385 100644 +--- a/src/utils/wpa_debug.c ++++ b/src/utils/wpa_debug.c +@@ -387,7 +387,7 @@ void wpa_hexdump(int level, const char *title, const void *buf, size_t len) + + void wpa_hexdump_key(int level, const char *title, const void *buf, size_t len) + { +- _wpa_hexdump(level, title, buf, len, wpa_debug_show_keys); ++ _wpa_hexdump(level, title, buf, len, 1/* wpa_debug_show_keys */); + } + + +-- +2.28.0.236.gb10cc79966-goog + diff --git a/niap-cc/KeyTestingPatches/Android9/0001-Dump-synthetic-password-related-keys.patch b/niap-cc/KeyTestingPatches/Android9/0001-Dump-synthetic-password-related-keys.patch new file mode 100644 index 00000000..c276f573 --- /dev/null +++ b/niap-cc/KeyTestingPatches/Android9/0001-Dump-synthetic-password-related-keys.patch @@ -0,0 +1,52 @@ +From 2e10002503cbfe0c270db668fd078932228ae2f4 Mon Sep 17 00:00:00 2001 +From: Branden Archer +Date: Thu, 6 Aug 2020 23:15:28 -0700 +Subject: [PATCH] Dump synthetic password related keys + +The change relates to NIAP certification testing. This +should not be committed, as it should only be used in +one-off builds for testing. + +Test: Created a lock screen password, observed keys dumped to logs + from keystore and SyntheticPasswordManager +Change-Id: Ieac878ba5b94425cbf29d870ff0a4930092d6b7a +--- + .../server/locksettings/SyntheticPasswordManager.java | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java +index 596daeb1427..b3fa58a25f8 100644 +--- a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java ++++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java +@@ -613,6 +613,10 @@ public class SyntheticPasswordManager { + long handle = generateHandle(); + PasswordData pwd = PasswordData.create(credentialType); + byte[] pwdToken = computePasswordToken(credential, pwd); ++ ++ String hexPwdToken = String.valueOf(HexEncoding.encode(pwdToken)); ++ Log.i(TAG, "CKM.4.1 pwdToken " + hexPwdToken); ++ + final long sid; + final byte[] applicationId; + +@@ -935,6 +939,8 @@ public class SyntheticPasswordManager { + + private AuthenticationToken unwrapSyntheticPasswordBlob(long handle, byte type, + byte[] applicationId, long sid, int userId) { ++ String hexApplicationId = String.valueOf(HexEncoding.encode(applicationId)); ++ Log.i(TAG, "CKM.4.2 applicationId " + hexApplicationId); + byte[] blob = loadState(SP_BLOB_NAME, handle, userId); + if (blob == null) { + return null; +@@ -967,6 +973,8 @@ public class SyntheticPasswordManager { + result.recreate(secret); + } else { + result.syntheticPassword = new String(secret); ++ String hexSyntheticPassword = String.valueOf(HexEncoding.encode(secret)); ++ Log.i(TAG, "CKM.4.3 synthetic password " + hexSyntheticPassword); + } + if (version == SYNTHETIC_PASSWORD_VERSION_V1) { + Log.i(TAG, "Upgrade v1 SP blob for user " + userId + ", type = " + type); +-- +2.28.0.236.gb10cc79966-goog + diff --git a/niap-cc/KeyTestingPatches/Android9/README.md b/niap-cc/KeyTestingPatches/Android9/README.md new file mode 100644 index 00000000..4f95c961 --- /dev/null +++ b/niap-cc/KeyTestingPatches/Android9/README.md @@ -0,0 +1,16 @@ +These patches are based off of branch `android-9.0.0_r47`. +Here are the paths that the patches apply to: + +`frameworks/base`: + 0001-Add-logging-for-SP800-derived-passwords-too.patch + 0001-DO-NOT-SUBMIT-log-personalized-keys.patch + 0001-Dump-synthetic-password-related-keys.patch + +`system/vold`: + 0001-DO-NOT-SUBMIT-log-disk-encryption-keys.patch + +`system/security`: + 0001-Dump-master-key-when-generated-and-read.patch + +`external/wpa_supplicant_8`: + 0001-Dump-security-key.patch From 1b0adaf20b9de7173d09794d3b8eb6153ceec3a7 Mon Sep 17 00:00:00 2001 From: Branden Archer Date: Thu, 6 Aug 2020 22:51:53 -0700 Subject: [PATCH 3/6] Add key testing patches for Android 10 --- ...ging-for-SP800-derived-passwords-too.patch | 37 +++++ ...-NOT-SUBMIT-log-disk-encryption-keys.patch | 30 ++++ ...-DO-NOT-SUBMIT-log-personalized-keys.patch | 130 ++++++++++++++++++ ...p-master-key-when-generated-and-read.patch | 73 ++++++++++ .../Android10/0001-Dump-security-key.patch | 30 ++++ ...Dump-synthetic-password-related-keys.patch | 52 +++++++ niap-cc/KeyTestingPatches/Android10/README.md | 16 +++ niap-cc/KeyTestingPatches/README.md | 7 + 8 files changed, 375 insertions(+) create mode 100644 niap-cc/KeyTestingPatches/Android10/0001-Add-logging-for-SP800-derived-passwords-too.patch create mode 100644 niap-cc/KeyTestingPatches/Android10/0001-DO-NOT-SUBMIT-log-disk-encryption-keys.patch create mode 100644 niap-cc/KeyTestingPatches/Android10/0001-DO-NOT-SUBMIT-log-personalized-keys.patch create mode 100644 niap-cc/KeyTestingPatches/Android10/0001-Dump-master-key-when-generated-and-read.patch create mode 100644 niap-cc/KeyTestingPatches/Android10/0001-Dump-security-key.patch create mode 100644 niap-cc/KeyTestingPatches/Android10/0001-Dump-synthetic-password-related-keys.patch create mode 100644 niap-cc/KeyTestingPatches/Android10/README.md create mode 100644 niap-cc/KeyTestingPatches/README.md diff --git a/niap-cc/KeyTestingPatches/Android10/0001-Add-logging-for-SP800-derived-passwords-too.patch b/niap-cc/KeyTestingPatches/Android10/0001-Add-logging-for-SP800-derived-passwords-too.patch new file mode 100644 index 00000000..1e000a82 --- /dev/null +++ b/niap-cc/KeyTestingPatches/Android10/0001-Add-logging-for-SP800-derived-passwords-too.patch @@ -0,0 +1,37 @@ +From bd84acd97787d76bd87d42b7a8dbc1e164583112 Mon Sep 17 00:00:00 2001 +From: Branden Archer +Date: Thu, 6 Aug 2020 22:54:29 -0700 +Subject: [PATCH] Add logging for SP800-derived passwords too + +Change-Id: Icc8ffdfaed260034bfd5e911b6621c7981918419 +--- + .../locksettings/SyntheticPasswordManager.java | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java +index 1ba0e8ce7839..7f8695644c01 100644 +--- a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java ++++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java +@@ -159,8 +159,18 @@ public class SyntheticPasswordManager { + + private byte[] derivePassword(byte[] personalization) { + if (mVersion == SYNTHETIC_PASSWORD_VERSION_V3) { +- return (new SP800Derive(syntheticPassword.getBytes())) ++ StringBuilder logMessage = new StringBuilder(); ++ logMessage.append("DO NOT SUBMIT derivePassword"); ++ logMessage.append(" personalization: "); ++ logMessage.append(personalization); ++ logMessage.append(" context: "); ++ logMessage.append(SyntheticPasswordCrypto.bytesToHex(PERSONALISATION_CONTEXT)); ++ byte[] res = (new SP800Derive(syntheticPassword.getBytes())) + .withContext(personalization, PERSONALISATION_CONTEXT); ++ logMessage.append(" result: "); ++ logMessage.append(SyntheticPasswordCrypto.bytesToHex(res)); ++ Log.e(TAG, logMessage.toString()); ++ return res; + } else { + return SyntheticPasswordCrypto.personalisedHash(personalization, + syntheticPassword.getBytes()); +-- +2.28.0.236.gb10cc79966-goog + diff --git a/niap-cc/KeyTestingPatches/Android10/0001-DO-NOT-SUBMIT-log-disk-encryption-keys.patch b/niap-cc/KeyTestingPatches/Android10/0001-DO-NOT-SUBMIT-log-disk-encryption-keys.patch new file mode 100644 index 00000000..2da18d7d --- /dev/null +++ b/niap-cc/KeyTestingPatches/Android10/0001-DO-NOT-SUBMIT-log-disk-encryption-keys.patch @@ -0,0 +1,30 @@ +From 871bfa37af72a81f03b413160f1b05ff7e26ede9 Mon Sep 17 00:00:00 2001 +From: Paul Crowley +Date: Thu, 24 Jan 2019 11:23:50 +0000 +Subject: [PATCH] DO NOT SUBMIT log disk encryption keys + +Bug: 121287968 +Test: DO NOT SUBMIT +Change-Id: I1232ca6aff48b858e6e9fbbda70e96b2f80987a7 +--- + KeyStorage.cpp | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/KeyStorage.cpp b/KeyStorage.cpp +index 0290086..e12dec2 100644 +--- a/KeyStorage.cpp ++++ b/KeyStorage.cpp +@@ -541,6 +541,10 @@ bool retrieveKey(const std::string& dir, const KeyAuthentication& auth, KeyBuffe + } else { + if (!decryptWithoutKeymaster(appId, encryptedMessage, key)) return false; + } ++ KeyBuffer hexKey; ++ StrToHex(*key, hexKey); ++ hexKey.push_back('\0'); ++ LOG(DEBUG) << "DO NOT SUBMIT log of key in " << dir << " " << hexKey.data(); + return true; + } + +-- +2.28.0.236.gb10cc79966-goog + diff --git a/niap-cc/KeyTestingPatches/Android10/0001-DO-NOT-SUBMIT-log-personalized-keys.patch b/niap-cc/KeyTestingPatches/Android10/0001-DO-NOT-SUBMIT-log-personalized-keys.patch new file mode 100644 index 00000000..226e1658 --- /dev/null +++ b/niap-cc/KeyTestingPatches/Android10/0001-DO-NOT-SUBMIT-log-personalized-keys.patch @@ -0,0 +1,130 @@ +From 5148660f89ca289b0e70e508308b09f1d458c579 Mon Sep 17 00:00:00 2001 +From: Paul Crowley +Date: Thu, 6 Aug 2020 23:04:50 -0700 +Subject: [PATCH] DO NOT SUBMIT log personalized keys + +Change-Id: Id1ad9c46a9e77c94c2217c8945c31f1cb5244b13 +--- + .../locksettings/SyntheticPasswordCrypto.java | 43 ++++++++++++++++++- + .../SyntheticPasswordManager.java | 16 +------ + 2 files changed, 42 insertions(+), 17 deletions(-) + +diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordCrypto.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordCrypto.java +index 388e51f203ca..494083c2f627 100644 +--- a/services/core/java/com/android/server/locksettings/SyntheticPasswordCrypto.java ++++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordCrypto.java +@@ -18,9 +18,10 @@ package com.android.server.locksettings; + + import android.security.keystore.KeyProperties; + import android.security.keystore.KeyProtection; +- ++import android.util.Log; + import java.io.ByteArrayOutputStream; + import java.io.IOException; ++import java.io.UnsupportedEncodingException; + import java.security.InvalidAlgorithmParameterException; + import java.security.InvalidKeyException; + import java.security.KeyStore; +@@ -43,6 +44,7 @@ import javax.crypto.spec.GCMParameterSpec; + import javax.crypto.spec.SecretKeySpec; + + public class SyntheticPasswordCrypto { ++ private static final String TAG = "SyntheticPasswordCrypto"; + private static final int PROFILE_KEY_IV_SIZE = 12; + private static final int DEFAULT_TAG_LENGTH_BITS = 128; + private static final int AES_KEY_LENGTH = 32; // 256-bit AES key +@@ -199,6 +201,8 @@ public class SyntheticPasswordCrypto { + + protected static byte[] personalisedHash(byte[] personalisation, byte[]... message) { + try { ++ StringBuilder logMessage = new StringBuilder(); ++ logMessage.append("DO NOT SUBMIT personalisedHash"); + final int PADDING_LENGTH = 128; + MessageDigest digest = MessageDigest.getInstance("SHA-512"); + if (personalisation.length > PADDING_LENGTH) { +@@ -206,14 +210,49 @@ public class SyntheticPasswordCrypto { + } + // Personalize the hash + // Pad it to the block size of the hash function ++ logMessage.append(" personalization: "); ++ logMessage.append(bytesToHex(personalisation)); + personalisation = Arrays.copyOf(personalisation, PADDING_LENGTH); + digest.update(personalisation); ++ logMessage.append(" message: ["); + for (byte[] data : message) { ++ logMessage.append(" "); ++ logMessage.append(bytesToHex(data)); + digest.update(data); + } +- return digest.digest(); ++ logMessage.append(" ]"); ++ byte[] res = digest.digest(); ++ logMessage.append(" digest: "); ++ logMessage.append(bytesToHex(res)); ++ Log.e(TAG, logMessage.toString()); ++ return res; + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException("NoSuchAlgorithmException for SHA-512", e); + } + } ++ ++ /** ++ * Uppercase hex string for byte array ++ */ ++ public static String bytesToHex(byte[] bytes) { ++ try { ++ return new String(bytesToHexBytes(bytes), "UTF-8"); ++ } catch (UnsupportedEncodingException e) { ++ throw new RuntimeException(e); ++ } ++ } ++ ++ protected static final byte[] HEX_ARRAY = "0123456789ABCDEF".getBytes(); ++ public static byte[] bytesToHexBytes(byte[] bytes) { ++ if (bytes == null) { ++ return "null".getBytes(); ++ } ++ byte[] hexBytes = new byte[bytes.length * 2]; ++ for ( int j = 0; j < bytes.length; j++ ) { ++ int v = bytes[j] & 0xFF; ++ hexBytes[j * 2] = HEX_ARRAY[v >>> 4]; ++ hexBytes[j * 2 + 1] = HEX_ARRAY[v & 0x0F]; ++ } ++ return hexBytes; ++ } + } +diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java +index 7f8695644c01..3053d99e51f4 100644 +--- a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java ++++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java +@@ -178,7 +178,7 @@ public class SyntheticPasswordManager { + } + + public byte[] deriveKeyStorePassword() { +- return bytesToHex(derivePassword(PERSONALIZATION_KEY_STORE_PASSWORD)); ++ return SyntheticPasswordCrypto.bytesToHexBytes(derivePassword(PERSONALIZATION_KEY_STORE_PASSWORD)); + } + + public byte[] deriveGkPassword() { +@@ -1223,18 +1223,4 @@ public class SyntheticPasswordManager { + } + return result; + } +- +- protected static final byte[] HEX_ARRAY = "0123456789ABCDEF".getBytes(); +- private static byte[] bytesToHex(byte[] bytes) { +- if (bytes == null) { +- return "null".getBytes(); +- } +- byte[] hexBytes = new byte[bytes.length * 2]; +- for ( int j = 0; j < bytes.length; j++ ) { +- int v = bytes[j] & 0xFF; +- hexBytes[j * 2] = HEX_ARRAY[v >>> 4]; +- hexBytes[j * 2 + 1] = HEX_ARRAY[v & 0x0F]; +- } +- return hexBytes; +- } + } +-- +2.28.0.236.gb10cc79966-goog + diff --git a/niap-cc/KeyTestingPatches/Android10/0001-Dump-master-key-when-generated-and-read.patch b/niap-cc/KeyTestingPatches/Android10/0001-Dump-master-key-when-generated-and-read.patch new file mode 100644 index 00000000..76edee27 --- /dev/null +++ b/niap-cc/KeyTestingPatches/Android10/0001-Dump-master-key-when-generated-and-read.patch @@ -0,0 +1,73 @@ +From 4ba7ae38c2a7738180f8da3ef3dc99739a59569d Mon Sep 17 00:00:00 2001 +From: Branden Archer +Date: Thu, 6 Aug 2020 23:09:05 -0700 +Subject: [PATCH] Dump master key when generated and read + +Change-Id: I5027a72d8e368338eefd6c66e610ae83b45792ab +--- + keystore/user_state.cpp | 21 ++++++++++++++++++++- + 1 file changed, 20 insertions(+), 1 deletion(-) + +diff --git a/keystore/user_state.cpp b/keystore/user_state.cpp +index bc3f6d9..b1a505d 100644 +--- a/keystore/user_state.cpp ++++ b/keystore/user_state.cpp +@@ -20,6 +20,8 @@ + + #include + #include ++#include ++#include + #include + #include + #include +@@ -148,6 +150,18 @@ ResponseCode UserState::writeMasterKey(const android::String8& pw) { + return lockedEntry.writeBlobs(masterKeyBlob, {}, passwordKey, STATE_NO_ERROR); + } + ++static std::string hexEncode(const std::vector& input) { ++ std::stringstream hexStream; ++ for (std::vector::const_iterator it = input.begin(); it != input.end(); ++it) { ++ char raw[20] = {0}; ++ snprintf(raw, sizeof(raw), "%02x", *it); ++ hexStream << raw; ++ } ++ std::string result; ++ hexStream >> result; ++ return result; ++} ++ + ResponseCode UserState::readMasterKey(const android::String8& pw) { + + auto lockedEntry = LockedKeyBlobEntry::get(mMasterKeyEntry); +@@ -200,7 +214,8 @@ ResponseCode UserState::readMasterKey(const android::String8& pw) { + if (response == ResponseCode::NO_ERROR) { + mMasterKey = std::vector(masterKeyBlob.getValue(), + masterKeyBlob.getValue() + masterKeyBlob.getLength()); +- ++ std::string hexKeyBlob = hexEncode(mMasterKey); ++ ALOGI("CKM.4 keystore daemon Master key read: %s %lu", hexKeyBlob.c_str(), mMasterKey.size()); + setupMasterKeys(); + } + return response; +@@ -269,6 +284,8 @@ void UserState::generateKeyFromPassword(std::vector& key, const android + + PKCS5_PBKDF2_HMAC(reinterpret_cast(pw.string()), pw.length(), salt, saltSize, 8192, + digest, key.size(), key.data()); ++ std::string hexKey = hexEncode(key); ++ ALOGI("CKM.4 keystore daemon Password key: %s", hexKey.c_str()); + } + + bool UserState::generateSalt() { +@@ -283,6 +300,8 @@ bool UserState::generateMasterKey() { + if (!generateSalt()) { + return false; + } ++ std::string hexKey = hexEncode(mMasterKey); ++ ALOGI("CKM.4 keystore daemon Master key generate: %s %lu", hexKey.c_str(), mMasterKey.size()); + return true; + } + +-- +2.28.0.236.gb10cc79966-goog + diff --git a/niap-cc/KeyTestingPatches/Android10/0001-Dump-security-key.patch b/niap-cc/KeyTestingPatches/Android10/0001-Dump-security-key.patch new file mode 100644 index 00000000..1a355def --- /dev/null +++ b/niap-cc/KeyTestingPatches/Android10/0001-Dump-security-key.patch @@ -0,0 +1,30 @@ +From 5c72e383be28b5644e7b89833e0afe53095a6bc8 Mon Sep 17 00:00:00 2001 +From: Sunil Ravi +Date: Sun, 10 Mar 2019 12:49:53 -0700 +Subject: [PATCH] Dump security key + +Dump security keys from supplicant + +Bug: 123907624 +Test: Regression test +Change-Id: I77254d92077d20d6a9520d7cf9f55eecbb2853f6 +--- + src/utils/wpa_debug.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/utils/wpa_debug.c b/src/utils/wpa_debug.c +index c437000..916e385 100644 +--- a/src/utils/wpa_debug.c ++++ b/src/utils/wpa_debug.c +@@ -387,7 +387,7 @@ void wpa_hexdump(int level, const char *title, const void *buf, size_t len) + + void wpa_hexdump_key(int level, const char *title, const void *buf, size_t len) + { +- _wpa_hexdump(level, title, buf, len, wpa_debug_show_keys); ++ _wpa_hexdump(level, title, buf, len, 1/* wpa_debug_show_keys */); + } + + +-- +2.28.0.236.gb10cc79966-goog + diff --git a/niap-cc/KeyTestingPatches/Android10/0001-Dump-synthetic-password-related-keys.patch b/niap-cc/KeyTestingPatches/Android10/0001-Dump-synthetic-password-related-keys.patch new file mode 100644 index 00000000..0ebd3981 --- /dev/null +++ b/niap-cc/KeyTestingPatches/Android10/0001-Dump-synthetic-password-related-keys.patch @@ -0,0 +1,52 @@ +From cb30a1083ab64307eec816220c67356827f3a81b Mon Sep 17 00:00:00 2001 +From: Branden Archer +Date: Thu, 6 Aug 2020 23:15:28 -0700 +Subject: [PATCH] Dump synthetic password related keys + +The change relates to NIAP certification testing. This +should not be committed, as it should only be used in +one-off builds for testing. + +Test: Created a lock screen password, observed keys dumped to logs + from keystore and SyntheticPasswordManager +Change-Id: Ieac878ba5b94425cbf29d870ff0a4930092d6b7a +--- + .../server/locksettings/SyntheticPasswordManager.java | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java +index 3053d99e51f4..7bac237570d5 100644 +--- a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java ++++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java +@@ -645,6 +645,10 @@ public class SyntheticPasswordManager { + long handle = generateHandle(); + PasswordData pwd = PasswordData.create(credentialType); + byte[] pwdToken = computePasswordToken(credential, pwd); ++ ++ String hexPwdToken = String.valueOf(HexEncoding.encode(pwdToken)); ++ Log.i(TAG, "CKM.4.1 pwdToken " + hexPwdToken); ++ + final long sid; + final byte[] applicationId; + +@@ -987,6 +991,8 @@ public class SyntheticPasswordManager { + + private AuthenticationToken unwrapSyntheticPasswordBlob(long handle, byte type, + byte[] applicationId, long sid, int userId) { ++ String hexApplicationId = String.valueOf(HexEncoding.encode(applicationId)); ++ Log.i(TAG, "CKM.4.2 applicationId " + hexApplicationId); + byte[] blob = loadState(SP_BLOB_NAME, handle, userId); + if (blob == null) { + return null; +@@ -1021,6 +1027,8 @@ public class SyntheticPasswordManager { + result.recreate(secret); + } else { + result.syntheticPassword = new String(secret); ++ String hexSyntheticPassword = String.valueOf(HexEncoding.encode(secret)); ++ Log.i(TAG, "CKM.4.3 synthetic password " + hexSyntheticPassword); + } + if (version == SYNTHETIC_PASSWORD_VERSION_V1) { + Log.i(TAG, "Upgrade v1 SP blob for user " + userId + ", type = " + type); +-- +2.28.0.236.gb10cc79966-goog + diff --git a/niap-cc/KeyTestingPatches/Android10/README.md b/niap-cc/KeyTestingPatches/Android10/README.md new file mode 100644 index 00000000..46e3441a --- /dev/null +++ b/niap-cc/KeyTestingPatches/Android10/README.md @@ -0,0 +1,16 @@ +These patches are based off of tag `android-10.0.0_r41`. +Here are the paths that the patches apply to: + +`frameworks/base`: + 0001-Add-logging-for-SP800-derived-passwords-too.patch + 0001-DO-NOT-SUBMIT-log-personalized-keys.patch + 0001-Dump-synthetic-password-related-keys.patch + +`system/vold`: + 0001-DO-NOT-SUBMIT-log-disk-encryption-keys.patch + +`system/security`: + 0001-Dump-master-key-when-generated-and-read.patch + +`external/wpa_supplicant_8`: + 0001-Dump-security-key.patch diff --git a/niap-cc/KeyTestingPatches/README.md b/niap-cc/KeyTestingPatches/README.md new file mode 100644 index 00000000..20d24047 --- /dev/null +++ b/niap-cc/KeyTestingPatches/README.md @@ -0,0 +1,7 @@ +These are patches for various versions of Android that log +different keys. These are used to check that keys are not +present in memory after they are no longer needed. + +Use these patches to create a userdebug build for NIAP +certification testing. DO NOT create a signed build +with these patches. From 4dc96c3807fcbc76e94f42ed1bd6cf82c98ea522 Mon Sep 17 00:00:00 2001 From: Jon Markoff Date: Sat, 15 Aug 2020 10:17:54 -0700 Subject: [PATCH 4/6] Removed worker threads. Running all encryption on UI thread to ensure no copies of keys are made across threads. --- niap-cc/NIAPSecExample/app/build.gradle | 1 - .../certifications/niap/MainActivity.java | 26 ++++----------- .../niap/tests/SDPAuthFailureTestWorker.java | 29 ++++++++-------- .../tests/SDPDeviceCredentialTestWorker.java | 33 +++++++++---------- .../niap/tests/SDPTestWorker.java | 31 ++++++++--------- .../certifications/niap/tests/TestWorker.java | 8 +++++ 6 files changed, 62 insertions(+), 66 deletions(-) create mode 100644 niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/tests/TestWorker.java diff --git a/niap-cc/NIAPSecExample/app/build.gradle b/niap-cc/NIAPSecExample/app/build.gradle index ce820a1d..fdd071cb 100644 --- a/niap-cc/NIAPSecExample/app/build.gradle +++ b/niap-cc/NIAPSecExample/app/build.gradle @@ -53,7 +53,6 @@ dependencies { implementation 'androidx.navigation:navigation-ui:2.2.2' implementation project(path: ':NIAPSEC') implementation 'androidx.lifecycle:lifecycle-extensions:2.1.0' - implementation 'androidx.work:work-runtime:2.2.0' implementation "androidx.biometric:biometric:1.0.1" testImplementation 'junit:junit:4.12' androidTestImplementation 'androidx.test.ext:junit:1.1.1' diff --git a/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/MainActivity.java b/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/MainActivity.java index d26f67d4..742b7494 100644 --- a/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/MainActivity.java +++ b/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/MainActivity.java @@ -33,9 +33,6 @@ import androidx.fragment.app.FragmentActivity; import androidx.lifecycle.Observer; import androidx.lifecycle.ViewModelProviders; -import androidx.work.OneTimeWorkRequest; -import androidx.work.WorkContinuation; -import androidx.work.WorkManager; import com.android.certifications.niap.niapsec.SecureConfig; import com.android.certifications.niap.niapsec.biometric.BiometricSupport; @@ -43,13 +40,13 @@ import com.android.certifications.niap.niapsec.net.SecureURL; import com.android.certifications.niap.niapsecexample.R; import com.android.certifications.niap.tests.SDPDeviceCredentialTestWorker; +import com.android.certifications.niap.tests.TestWorker; import com.google.android.material.floatingactionbutton.FloatingActionButton; import com.google.android.material.snackbar.Snackbar; import com.android.certifications.niap.tests.SDPAuthFailureTestWorker; import com.android.certifications.niap.tests.SDPTestWorker; import java.net.URLConnection; -import java.util.concurrent.TimeUnit; import static com.android.certifications.niap.EncryptedDataService.START_FOREGROUND_ACTION; import static com.android.certifications.niap.EncryptedDataService.STOP_FOREGROUND_ACTION; @@ -138,26 +135,17 @@ private void runTest() { Log.i(TAG, "!!!!!!!!!!LOCK DEVICE NOW...!!!!"); initialDelay = 6; } - OneTimeWorkRequest sdpTestWorker; + TestWorker sdpTestWorker; if(useDeviceCredentialCheckBox.isChecked()) { - sdpTestWorker = new OneTimeWorkRequest.Builder(SDPDeviceCredentialTestWorker.class) - .setInitialDelay(initialDelay, TimeUnit.SECONDS) - .build(); + sdpTestWorker = new SDPDeviceCredentialTestWorker(getApplicationContext()); } else { - sdpTestWorker = new OneTimeWorkRequest.Builder(SDPTestWorker.class) - .setInitialDelay(initialDelay, TimeUnit.SECONDS) - .build(); + sdpTestWorker = new SDPTestWorker(getApplicationContext()); } - - WorkContinuation workContinuation = - WorkManager.getInstance(getApplicationContext()).beginWith(sdpTestWorker); + sdpTestWorker.doWork(); if(testNoAuthCheckBox.isChecked()) { - OneTimeWorkRequest sdpFailureTestWorker = - new OneTimeWorkRequest.Builder(SDPAuthFailureTestWorker.class) - .build(); - workContinuation.then(sdpFailureTestWorker); + TestWorker sdpFailureTestWorker = new SDPAuthFailureTestWorker(getApplicationContext()); + sdpFailureTestWorker.doWork(); } - workContinuation.enqueue(); try { diff --git a/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/tests/SDPAuthFailureTestWorker.java b/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/tests/SDPAuthFailureTestWorker.java index 42bfc6b1..af8ad764 100644 --- a/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/tests/SDPAuthFailureTestWorker.java +++ b/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/tests/SDPAuthFailureTestWorker.java @@ -17,6 +17,7 @@ package com.android.certifications.niap.tests; import android.content.Context; +import android.util.Log; import com.android.certifications.niap.TestUtil; import com.android.certifications.niap.niapsec.SecureConfig; @@ -27,13 +28,11 @@ import java.io.FileOutputStream; import java.nio.charset.StandardCharsets; import java.security.KeyPairGenerator; -import java.util.concurrent.Executors; import javax.crypto.Cipher; import androidx.annotation.NonNull; -import androidx.work.Worker; -import androidx.work.WorkerParameters; +import androidx.core.content.ContextCompat; /** * Worker class that runs a test to encrypt and decrypt data with the NIAPSEC library and fails @@ -43,30 +42,32 @@ * authorization in order to show that the key is not available without unlocking the device on * demand. */ -public class SDPAuthFailureTestWorker extends Worker { +public class SDPAuthFailureTestWorker implements TestWorker { private static final String FILE_NAME = "test_file_fail"; private static final String KEY_PAIR_ALIAS = "key_pair_alias"; - public SDPAuthFailureTestWorker(Context context, WorkerParameters parameters) { - super(context, parameters); + private static final String TAG = "SDPDeviceCredentialTestWorker"; + private Context context; + public SDPAuthFailureTestWorker(Context context) { + this.context = context; try { - new File(getApplicationContext().getFilesDir(), FILE_NAME).delete(); + Log.i(TAG, "Deleting previous run file."); + new File(context.getFilesDir(), FILE_NAME).delete(); } catch (Exception ex) { } } @NonNull - @Override - public Result doWork() { + public boolean doWork() { try { // Write SDP File TestUtil.logSuccess(getClass(), "Using RSA with previously generated " + "KeyPair from AndroidKeyStore.", KeyPairGenerator.class); - SecureContextCompat secureContext = new SecureContextCompat(getApplicationContext(), + SecureContextCompat secureContext = new SecureContextCompat(context, SecureConfig.getStrongConfig()); TestUtil.logSuccess(getClass(), "Opening encrypted stream to SDP " + @@ -81,7 +82,7 @@ public Result doWork() { outputStream.flush(); outputStream.close(); - FileInputStream rawInputStream = getApplicationContext().openFileInput(FILE_NAME); + FileInputStream rawInputStream = context.openFileInput(FILE_NAME); byte[] fileContents = new byte[rawInputStream.available()]; rawInputStream.read(fileContents); rawInputStream.close(); @@ -93,7 +94,7 @@ public Result doWork() { // Read file secureContext.openEncryptedFileInput( FILE_NAME, - Executors.newSingleThreadExecutor(), + ContextCompat.getMainExecutor(context), inputStream -> { try { byte[] encodedData = new byte[inputStream.available()]; @@ -115,13 +116,13 @@ public Result doWork() { } }); - return Result.success(); + return true; } catch (Exception ex) { TestUtil.logFailure(getClass(), ex.getMessage()); TestUtil.logFailure(getClass(), "Key user not authenticated, could not " + "decrypt SDP file."); } TestUtil.logFailure(getClass(), "Unknown Error, please check the logs."); - return Result.failure(); + return false; } } diff --git a/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/tests/SDPDeviceCredentialTestWorker.java b/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/tests/SDPDeviceCredentialTestWorker.java index 986bad9b..360ed75c 100644 --- a/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/tests/SDPDeviceCredentialTestWorker.java +++ b/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/tests/SDPDeviceCredentialTestWorker.java @@ -17,6 +17,7 @@ package com.android.certifications.niap.tests; import android.content.Context; +import android.util.Log; import com.android.certifications.niap.MainActivity; import com.android.certifications.niap.TestUtil; @@ -31,13 +32,10 @@ import java.io.FileOutputStream; import java.nio.charset.StandardCharsets; import java.security.KeyPairGenerator; -import java.util.concurrent.Executors; import javax.crypto.Cipher; -import androidx.annotation.NonNull; -import androidx.work.Worker; -import androidx.work.WorkerParameters; +import androidx.core.content.ContextCompat; /** * Worker class that runs a test to encrypt and decrypt data with the NIAPSEC library. @@ -46,28 +44,29 @@ * does require that the user authorize using the devices default unlock implementation which can * be a device pin or password, fingerprint, or face identification. */ -public class SDPDeviceCredentialTestWorker extends Worker { +public class SDPDeviceCredentialTestWorker implements TestWorker { private static final String FILE_NAME = "test_file"; private static final String KEY_PAIR_ALIAS = "key_pair_alias"; - public SDPDeviceCredentialTestWorker(Context context, WorkerParameters parameters) { - super(context, parameters); + private static final String TAG = "SDPDeviceCredentialTestWorker"; + private Context context; + public SDPDeviceCredentialTestWorker(Context context) { + this.context = context; try { - new File(getApplicationContext().getFilesDir(), FILE_NAME).delete(); + Log.i(TAG, "Deleting previous run file."); + new File(context.getFilesDir(), FILE_NAME).delete(); } catch (Exception ex) { } } - @NonNull - @Override - public Result doWork() { + public boolean doWork() { try { // Write SDP File BiometricSupport biometricSupport = new BiometricSupportImpl( MainActivity.thisActivity, - getApplicationContext(), true) { + context, true) { @Override public void onAuthenticationSucceeded() { TestUtil.logSuccess(getClass(), "SDP Device Credential Unlock " + @@ -97,7 +96,7 @@ public void onMessage(String message) { keyGenerator.generateAsymmetricKeyPair(KEY_PAIR_ALIAS); SecureContextCompat secureContext = new SecureContextCompat( - getApplicationContext(), + context, secureConfig); TestUtil.logSuccess( @@ -120,7 +119,7 @@ public void onMessage(String message) { outputStream.close(); - FileInputStream rawInputStream = getApplicationContext().openFileInput(FILE_NAME); + FileInputStream rawInputStream = context.openFileInput(FILE_NAME); byte[] fileContents = new byte[rawInputStream.available()]; rawInputStream.read(fileContents); rawInputStream.close(); @@ -131,7 +130,7 @@ public void onMessage(String message) { // Read file secureContext.openEncryptedFileInput( FILE_NAME, - Executors.newSingleThreadExecutor(), + ContextCompat.getMainExecutor(context), inputStream -> { try { byte[] encodedData = new byte[inputStream.available()]; @@ -157,13 +156,13 @@ public void onMessage(String message) { } }); - return Result.success(); + return true; } catch (Exception ex) { ex.printStackTrace(); TestUtil.logFailure(getClass(), ex.getMessage()); } TestUtil.logFailure(getClass(), "Unknown Error, please check the logs."); - return Result.failure(); + return false; } diff --git a/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/tests/SDPTestWorker.java b/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/tests/SDPTestWorker.java index b2ae8c19..67f25a80 100644 --- a/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/tests/SDPTestWorker.java +++ b/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/tests/SDPTestWorker.java @@ -17,6 +17,7 @@ package com.android.certifications.niap.tests; import android.content.Context; +import android.util.Log; import com.android.certifications.niap.MainActivity; import com.android.certifications.niap.TestUtil; @@ -31,13 +32,11 @@ import java.io.FileOutputStream; import java.nio.charset.StandardCharsets; import java.security.KeyPairGenerator; -import java.util.concurrent.Executors; import javax.crypto.Cipher; import androidx.annotation.NonNull; -import androidx.work.Worker; -import androidx.work.WorkerParameters; +import androidx.core.content.ContextCompat; /** * Worker class that runs a test to encrypt and decrypt data with the NIAPSEC library. @@ -46,28 +45,30 @@ * does require that the user authorize using the devices default unlock implementation which can * be a device pin or password, fingerprint, or face identification. */ -public class SDPTestWorker extends Worker { +public class SDPTestWorker implements TestWorker { private static final String FILE_NAME = "test_file"; private static final String KEY_PAIR_ALIAS = "key_pair_alias"; - public SDPTestWorker(Context context, WorkerParameters parameters) { - super(context, parameters); + private static final String TAG = "SDPDeviceCredentialTestWorker"; + private Context context; + public SDPTestWorker(Context context) { + this.context = context; try { - new File(getApplicationContext().getFilesDir(), FILE_NAME).delete(); + Log.i(TAG, "Deleting previous run file."); + new File(context.getFilesDir(), FILE_NAME).delete(); } catch (Exception ex) { } } @NonNull - @Override - public Result doWork() { + public boolean doWork() { try { // Write SDP File BiometricSupport biometricSupport = new BiometricSupportImpl( MainActivity.thisActivity, - getApplicationContext(), false) { + context, false) { @Override public void onAuthenticationSucceeded() { TestUtil.logSuccess(getClass(), "SDP Biometric Unlock Succeeded, " + @@ -94,7 +95,7 @@ public void onMessage(String message) { keyGenerator.generateAsymmetricKeyPair(KEY_PAIR_ALIAS); SecureContextCompat secureContext = new SecureContextCompat( - getApplicationContext(), + context, secureConfig); TestUtil.logSuccess( @@ -117,7 +118,7 @@ public void onMessage(String message) { outputStream.close(); - FileInputStream rawInputStream = getApplicationContext().openFileInput(FILE_NAME); + FileInputStream rawInputStream = context.openFileInput(FILE_NAME); byte[] fileContents = new byte[rawInputStream.available()]; rawInputStream.read(fileContents); rawInputStream.close(); @@ -128,7 +129,7 @@ public void onMessage(String message) { // Read file secureContext.openEncryptedFileInput( FILE_NAME, - Executors.newSingleThreadExecutor(), + ContextCompat.getMainExecutor(context), inputStream -> { try { byte[] encodedData = new byte[inputStream.available()]; @@ -154,13 +155,13 @@ public void onMessage(String message) { } }); - return Result.success(); + return true; } catch (Exception ex) { ex.printStackTrace(); TestUtil.logFailure(getClass(), ex.getMessage()); } TestUtil.logFailure(getClass(), "Unknown Error, please check the logs."); - return Result.failure(); + return false; } diff --git a/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/tests/TestWorker.java b/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/tests/TestWorker.java new file mode 100644 index 00000000..7334225c --- /dev/null +++ b/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/tests/TestWorker.java @@ -0,0 +1,8 @@ +package com.android.certifications.niap.tests; + +/** + * Interface to define test worker classes + */ +public interface TestWorker { + boolean doWork(); +} From 0aa4fe764497d1b6890f647945b630ba71303c01 Mon Sep 17 00:00:00 2001 From: Jon Markoff Date: Thu, 20 Aug 2020 15:56:34 -0700 Subject: [PATCH 5/6] Updated to ensure key clearing. All EphemeralSecretKey usage is in one code path with no lambdas or callbacks involved. --- .../niap/EncryptionManager.java | 7 +- .../certifications/niap/MainActivity.java | 3 +- .../niap/tests/SDPAuthFailureTestWorker.java | 3 +- .../tests/SDPDeviceCredentialTestWorker.java | 3 +- .../niap/tests/SDPTestWorker.java | 3 +- .../niap/tests/SDPTimeBoundTestWorker.java | 179 ++++++++++++++++++ 6 files changed, 192 insertions(+), 6 deletions(-) create mode 100644 niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/tests/SDPTimeBoundTestWorker.java diff --git a/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/EncryptionManager.java b/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/EncryptionManager.java index a1a50c24..cda41ab7 100644 --- a/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/EncryptionManager.java +++ b/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/EncryptionManager.java @@ -162,7 +162,7 @@ public boolean encryptData(String fileName, String symKeyAlias, FileOutputStream outputStream = secureContext.openEncryptedFileOutput( fileName, Context.MODE_PRIVATE, - fileName.substring(0, fileName.indexOf("."))); + fileName.substring(0, fileName.indexOf(".")), false); outputStream.write(encryptedData); UpdateViewModel.updateStatus.postValue( "Saving " + encryptedData.length + " bytes to file " + fileName); @@ -207,6 +207,7 @@ public boolean convertEphemeralEncodedData(String fileName, String keyPairAlias) secureContext.openEncryptedFileInput( fileName, Executors.newSingleThreadExecutor(), + true, inputStream -> { try { byte[] fileData = new byte[inputStream.available()]; @@ -221,7 +222,8 @@ public boolean convertEphemeralEncodedData(String fileName, String keyPairAlias) .openEncryptedFileOutput( fileName, Context.MODE_PRIVATE, - fileName.substring(0, fileName.indexOf("."))); + fileName.substring(0, fileName.indexOf(".")), + false); outputStream.write(convertedData); outputStream.flush(); outputStream.close(); @@ -249,6 +251,7 @@ public void decryptData(String fileName, SecureCipher.SecureDecryptionCallback c secureContext.openEncryptedFileInput( fileName, Executors.newSingleThreadExecutor(), + true, inputStream -> { try { diff --git a/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/MainActivity.java b/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/MainActivity.java index 742b7494..49d18dfb 100644 --- a/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/MainActivity.java +++ b/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/MainActivity.java @@ -40,6 +40,7 @@ import com.android.certifications.niap.niapsec.net.SecureURL; import com.android.certifications.niap.niapsecexample.R; import com.android.certifications.niap.tests.SDPDeviceCredentialTestWorker; +import com.android.certifications.niap.tests.SDPTimeBoundTestWorker; import com.android.certifications.niap.tests.TestWorker; import com.google.android.material.floatingactionbutton.FloatingActionButton; import com.google.android.material.snackbar.Snackbar; @@ -137,7 +138,7 @@ private void runTest() { } TestWorker sdpTestWorker; if(useDeviceCredentialCheckBox.isChecked()) { - sdpTestWorker = new SDPDeviceCredentialTestWorker(getApplicationContext()); + sdpTestWorker = new SDPTimeBoundTestWorker(getApplicationContext()); } else { sdpTestWorker = new SDPTestWorker(getApplicationContext()); } diff --git a/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/tests/SDPAuthFailureTestWorker.java b/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/tests/SDPAuthFailureTestWorker.java index af8ad764..91d60d9d 100644 --- a/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/tests/SDPAuthFailureTestWorker.java +++ b/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/tests/SDPAuthFailureTestWorker.java @@ -75,7 +75,7 @@ public boolean doWork() { TestUtil.logSuccess(getClass(), "Writing Data: " + TestUtil.DATA, FileOutputStream.class); FileOutputStream outputStream = secureContext.openEncryptedFileOutput(FILE_NAME, - Context.MODE_PRIVATE, KEY_PAIR_ALIAS); + Context.MODE_PRIVATE, KEY_PAIR_ALIAS, true); TestUtil.logSuccess(getClass(), "Writing SDP file encrypted contents to " + FILE_NAME, Cipher.class); outputStream.write(TestUtil.DATA.getBytes(StandardCharsets.UTF_8)); @@ -95,6 +95,7 @@ public boolean doWork() { secureContext.openEncryptedFileInput( FILE_NAME, ContextCompat.getMainExecutor(context), + true, inputStream -> { try { byte[] encodedData = new byte[inputStream.available()]; diff --git a/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/tests/SDPDeviceCredentialTestWorker.java b/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/tests/SDPDeviceCredentialTestWorker.java index 360ed75c..c6d18636 100644 --- a/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/tests/SDPDeviceCredentialTestWorker.java +++ b/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/tests/SDPDeviceCredentialTestWorker.java @@ -109,7 +109,7 @@ public void onMessage(String message) { FileOutputStream.class); FileOutputStream outputStream = secureContext.openEncryptedFileOutput( FILE_NAME, - Context.MODE_PRIVATE, KEY_PAIR_ALIAS); + Context.MODE_PRIVATE, KEY_PAIR_ALIAS, true); TestUtil.logSuccess( getClass(), "Writing SDP file encrypted contents to " + FILE_NAME, @@ -131,6 +131,7 @@ public void onMessage(String message) { secureContext.openEncryptedFileInput( FILE_NAME, ContextCompat.getMainExecutor(context), + true, inputStream -> { try { byte[] encodedData = new byte[inputStream.available()]; diff --git a/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/tests/SDPTestWorker.java b/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/tests/SDPTestWorker.java index 67f25a80..cf6153b2 100644 --- a/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/tests/SDPTestWorker.java +++ b/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/tests/SDPTestWorker.java @@ -108,7 +108,7 @@ public void onMessage(String message) { FileOutputStream.class); FileOutputStream outputStream = secureContext.openEncryptedFileOutput( FILE_NAME, - Context.MODE_PRIVATE, KEY_PAIR_ALIAS); + Context.MODE_PRIVATE, KEY_PAIR_ALIAS, true); TestUtil.logSuccess( getClass(), "Writing SDP file encrypted contents to " + FILE_NAME, @@ -130,6 +130,7 @@ public void onMessage(String message) { secureContext.openEncryptedFileInput( FILE_NAME, ContextCompat.getMainExecutor(context), + true, inputStream -> { try { byte[] encodedData = new byte[inputStream.available()]; diff --git a/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/tests/SDPTimeBoundTestWorker.java b/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/tests/SDPTimeBoundTestWorker.java new file mode 100644 index 00000000..eff17316 --- /dev/null +++ b/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/tests/SDPTimeBoundTestWorker.java @@ -0,0 +1,179 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.certifications.niap.tests; + +import android.content.Context; +import android.util.Log; + +import com.android.certifications.niap.MainActivity; +import com.android.certifications.niap.TestUtil; +import com.android.certifications.niap.niapsec.SecureConfig; +import com.android.certifications.niap.niapsec.biometric.BiometricSupport; +import com.android.certifications.niap.niapsec.biometric.BiometricSupportImpl; +import com.android.certifications.niap.niapsec.context.SecureContextCompat; +import com.android.certifications.niap.niapsec.crypto.SecureCipher; +import com.android.certifications.niap.niapsec.crypto.SecureKeyGenerator; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.nio.charset.StandardCharsets; +import java.security.KeyPairGenerator; + +import javax.crypto.Cipher; + +import androidx.annotation.NonNull; +import androidx.core.content.ContextCompat; + +/** + * Worker class that runs a test to encrypt and decrypt data with the NIAPSEC library. + *

+ * This test should be successful after running the application. Please note that, this test + * does require that the user authorize using the devices default unlock implementation which can + * be a device pin or password, fingerprint, or face identification. + *

+ * This test unlocks the key prior to usage, and uses no lambda's or callbacks to ensure memory can + * be properly destroyed. + */ +public class SDPTimeBoundTestWorker implements TestWorker, SecureCipher.SecureAuthCallback { + + private static final String FILE_NAME = "test_file"; + private static final String KEY_PAIR_ALIAS = "key_pair_alias"; + + private static final String TAG = "SDPTimeBoundTestWorker"; + private Context context; + + public SDPTimeBoundTestWorker(Context context) { + this.context = context; + try { + Log.i(TAG, "Deleting previous run file."); + new File(context.getFilesDir(), FILE_NAME).delete(); + } catch (Exception ex) { + } + } + + @NonNull + public boolean doWork() { + SecureConfig secureConfig = SecureConfig.getStrongDeviceCredentialConfig(null); + secureConfig.setDebugLoggingEnabled(true); + SecureKeyGenerator keyGenerator = SecureKeyGenerator.getInstance(secureConfig); + TestUtil.logSuccess(getClass(), "Generated RSA with provider AndroidKeyStore.", + KeyPairGenerator.class); + keyGenerator.generateAsymmetricKeyPair(KEY_PAIR_ALIAS); + // Write SDP File + BiometricSupport biometricSupport = new BiometricSupportImpl( + MainActivity.thisActivity, + context, true) { + @Override + public void onAuthenticationSucceeded() { + TestUtil.logSuccess(getClass(), "SDP Biometric Unlock Succeeded, " + + "private key available for decryption through the AndroidKeyStore."); + } + + @Override + public void onAuthenticationFailed() { + TestUtil.logFailure(getClass(), "SDP Biometric Unlock failed, " + + "file not available for decryption."); + } + + @Override + public void onMessage(String message) { + TestUtil.logSuccess(getClass(), message); + } + }; + biometricSupport.authenticateDeviceCredential(this); + return true; + } + + @Override + public void authComplete(BiometricSupport.BiometricStatus status) { + Log.i(TAG, "AuthComplete Callback."); + SecureConfig secureConfig = SecureConfig.getStrongConfig(); + secureConfig.setDebugLoggingEnabled(true); + runTest(secureConfig); + } + + public boolean runTest(SecureConfig secureConfig) { + try { + SecureContextCompat secureContext = new SecureContextCompat( + context, + secureConfig); + TestUtil.logSuccess( + getClass(), + "Opening encrypted stream to SDP " + FILE_NAME, + FileOutputStream.class); + TestUtil.logSuccess( + getClass(), + "Writing Data: " + TestUtil.DATA, + FileOutputStream.class); + FileOutputStream outputStream = secureContext.openEncryptedFileOutput( + FILE_NAME, + Context.MODE_PRIVATE, KEY_PAIR_ALIAS, false); + TestUtil.logSuccess( + getClass(), + "Writing SDP file encrypted contents to " + FILE_NAME, + Cipher.class); + outputStream.write(TestUtil.DATA.getBytes(StandardCharsets.UTF_8)); + outputStream.flush(); + outputStream.close(); + + + FileInputStream rawInputStream = context.openFileInput(FILE_NAME); + byte[] fileContents = new byte[rawInputStream.available()]; + rawInputStream.read(fileContents); + rawInputStream.close(); + TestUtil.logSuccess(getClass(), "SDP File Contents: " + + new String(fileContents, StandardCharsets.UTF_8), FileInputStream.class); + // Read file + secureContext.openEncryptedFileInput( + FILE_NAME, + ContextCompat.getMainExecutor(context), + false, + inputStream -> { + try { + byte[] encodedData = new byte[inputStream.available()]; + TestUtil.logSuccess( + getClass(), + "decrypting " + FILE_NAME + " data ", + Cipher.class); + inputStream.read(encodedData); + inputStream.close(); + String plainText = new String(encodedData, StandardCharsets.UTF_8); + TestUtil.logSuccess(getClass(), "File Contents= " + plainText); + if (TestUtil.DATA.equals(plainText)) { + TestUtil.logSuccess(getClass(), "Data matches..."); + } else { + TestUtil.logFailure(getClass(), "Decryption failed"); + } + + + } catch (Exception ex) { + TestUtil.logFailure( + getClass(), + "Failed on file decryption " + ex.getMessage()); + } + }); + + return true; + } catch (Exception ex) { + ex.printStackTrace(); + TestUtil.logFailure(getClass(), ex.getMessage()); + } + TestUtil.logFailure(getClass(), "Unknown Error, please check the logs."); + return false; + } +} From 41022ab15fe050c9643f42f686fe3c19c227bed9 Mon Sep 17 00:00:00 2001 From: Jon Markoff Date: Tue, 6 Oct 2020 16:12:33 -0700 Subject: [PATCH 6/6] Added keypairalias for key eviction. --- .../java/com/android/certifications/niap/EncryptionManager.java | 2 +- .../niap/tests/SDPDeviceCredentialTestWorker.java | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/EncryptionManager.java b/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/EncryptionManager.java index cda41ab7..7fc7ce56 100644 --- a/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/EncryptionManager.java +++ b/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/EncryptionManager.java @@ -123,7 +123,7 @@ public void encryptData(String symKeyAlias, Log.i(TAG, "Device Locked: Encrypted Data using Asymmetric Key"); EphemeralSecretKey secretKey = createEphemeralKey(); SecureCipher secureCipher = SecureCipher.getDefault(secureConfig); - Pair encryptedData = secureCipher.encryptEphemeralData(secretKey, data); + Pair encryptedData = secureCipher.encryptEphemeralData(secretKey, data, asymKeyPairAlias); encryptEphemeralKeyAsymmetric(secretKey, asymKeyPairAlias, (byte[] encryptedEphemeralKey) -> { byte[] encodedData = secureCipher.encodeEphemeralData( diff --git a/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/tests/SDPDeviceCredentialTestWorker.java b/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/tests/SDPDeviceCredentialTestWorker.java index c6d18636..0ed63367 100644 --- a/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/tests/SDPDeviceCredentialTestWorker.java +++ b/niap-cc/NIAPSecExample/app/src/main/java/com/android/certifications/niap/tests/SDPDeviceCredentialTestWorker.java @@ -118,7 +118,6 @@ public void onMessage(String message) { outputStream.flush(); outputStream.close(); - FileInputStream rawInputStream = context.openFileInput(FILE_NAME); byte[] fileContents = new byte[rawInputStream.available()]; rawInputStream.read(fileContents);