blob: d664e55db7139763a70ba7456bbb54ff20b622ef [file] [log] [blame]
/*
* Copyright (C) 2016 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.cts.verifier.security;
import com.android.cts.verifier.ConditionalTest;
import android.app.AlertDialog;
import android.app.KeyguardManager;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import com.android.cts.verifier.PassFailButtons;
import com.android.cts.verifier.R;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.util.Arrays;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
@ConditionalTest(excluded_features = "android.hardware.type.television:android.software.leanback:android.hardware.type.watch")
public class WiFiCACertificateBugTest extends PassFailButtons.Activity {
private static final String CERT_ASSET_NAME = "myCA.cer";
private File certStagingFile = new File("/sdcard/", CERT_ASSET_NAME);
private KeyguardManager mKeyguardManager;
private boolean testResult;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.ca_certificate_wifi);
setPassFailButtonClickListeners();
setInfoResources(R.string.sec_wifi_ca_cert_test, R.string.sec_wifi_ca_cert_test_info, -1);
mKeyguardManager = (KeyguardManager) getSystemService(KEYGUARD_SERVICE);
getPassButton().setEnabled(false);
Button transferCertificateButton = (Button) findViewById(R.id.transfer_ca_certificate);
final Button goToSettingsButton = (Button) findViewById(R.id.gotosettings);
goToSettingsButton.setEnabled(false);
final Button goToWifiSettingsButton = (Button) findViewById(R.id.gotowifisettings);
goToWifiSettingsButton.setEnabled(false);
final Button certificateTrustCheckButton = (Button) findViewById(R.id.check_cert_trust);
certificateTrustCheckButton.setEnabled(false);
final TextView finalStepTextView = (TextView) findViewById(R.id.clear_creds_textView);
goToSettingsButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//Launch settings of the device
startActivityForResult(
new Intent(android.provider.Settings.ACTION_SECURITY_SETTINGS), 0);
if (testResult) {
getPassButton().setEnabled(true);
finalStepTextView.setText(getResources().getString(R.string
.sec_pass_test_instruction));
} else {
finalStepTextView.setText(getResources().getString(R.string
.sec_fail_test_instruction));
}
}
});
goToWifiSettingsButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//Launch WiFi settings of the device
startActivity(new Intent(android.provider.Settings.ACTION_WIFI_SETTINGS));
}
});
transferCertificateButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (transferCertificateToDevice()) {
openDialog(getResources().getString(R.string.sec_file_transferred_text));
goToSettingsButton.setEnabled(true);
goToWifiSettingsButton.setEnabled(true);
certificateTrustCheckButton.setEnabled(true);
} else {
openDialog(getResources().getString(R.string.sec_file_transfer_failed));
}
}
});
certificateTrustCheckButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Certificate caCert = readCertificate(convertFileToByteArray(certStagingFile));
if (caCert != null) {
if (isCaCertificateTrusted(caCert)) {
testResult = false;
openDialog(getResources().getString(R.string.sec_cert_trusted_text));
} else {
testResult = true;
openDialog(getResources().getString(R.string.sec_cert_nottrusted_text));
}
} else {
openDialog(getResources().getString(R.string.sec_read_cert_exception));
}
}
});
}
/**
* Transfers the certificate file to the internal storage i.e. /sdcard/ of the device
*
* @return
*/
private boolean transferCertificateToDevice() {
InputStream is = null;
FileOutputStream os = null;
try {
try {
is = getAssets().open(CERT_ASSET_NAME);
os = new FileOutputStream(certStagingFile);
byte[] buffer = new byte[1024];
int length;
while ((length = is.read(buffer)) > 0) {
os.write(buffer, 0, length);
}
} finally {
if (is != null) is.close();
if (os != null) os.close();
certStagingFile.setReadable(true, false);
}
} catch (IOException ioe) {
return false;
}
return true;
}
/**
* Converts the certificate file into byte array
*
* @param file
* @return
*/
private static byte[] convertFileToByteArray(File file) {
byte[] byteArray = null;
try {
InputStream inputStream = new FileInputStream(file);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] bytes = new byte[1024 * 8];
int bytesRead = 0;
while ((bytesRead = inputStream.read(bytes)) != -1) {
bos.write(bytes, 0, bytesRead);
}
byteArray = bos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
}
return byteArray;
}
/**
* Opens the dialog with the message passed as an argument
*
* @param message
*/
private void openDialog(String message) {
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
alertDialogBuilder.setMessage(message);
alertDialogBuilder.setPositiveButton(getResources().getString(R.string
.hifi_ultrasound_test_ok), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int arg1) {
dialog.dismiss();
}
});
AlertDialog alertDialog = alertDialogBuilder.create();
alertDialog.show();
}
/**
* Checks if the exploit certificate is trusted by the system
*
* @param caCert
* @return
* @throws GeneralSecurityException
* @throws CertificateException
*/
private boolean isCaCertificateTrusted(Certificate caCert) {
boolean trusted = false;
TrustManagerFactory tmf = null;
try {
tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init((KeyStore) null);
} catch (NoSuchAlgorithmException | KeyStoreException e) {
return trusted;
}
for (TrustManager trustManager : tmf.getTrustManagers()) {
if (trustManager instanceof X509TrustManager) {
final X509TrustManager tm = (X509TrustManager) trustManager;
if (Arrays.asList(tm.getAcceptedIssuers()).contains(caCert)) {
trusted = true;
break;
}
}
}
return trusted;
}
/**
* Convert an encoded certificate back into a {@link Certificate}.
* <p/>
* Instantiates a fresh CertificateFactory every time for repeatability.
*/
private static Certificate readCertificate(byte[] certBuffer) {
CertificateFactory certFactory = null;
try {
certFactory = CertificateFactory.getInstance("X.509");
return certFactory.generateCertificate(new ByteArrayInputStream(certBuffer));
} catch (CertificateException e) {
return null;
}
}
}