diff --git a/app/src/main/java/eu/faircode/email/AdapterCertificate.java b/app/src/main/java/eu/faircode/email/AdapterCertificate.java index 2a97541465..6d8e294e25 100644 --- a/app/src/main/java/eu/faircode/email/AdapterCertificate.java +++ b/app/src/main/java/eu/faircode/email/AdapterCertificate.java @@ -23,6 +23,7 @@ import android.content.Context; import android.graphics.Typeface; import android.os.Bundle; import android.text.SpannableString; +import android.text.TextUtils; import android.text.style.RelativeSizeSpan; import android.text.style.StyleSpan; import android.view.LayoutInflater; @@ -68,6 +69,7 @@ public class AdapterCertificate extends RecyclerView.Adapter usage = certificate.getKeyUsage(); + if (certificate.isSelfSigned()) + usage.add(0, "selfSigned"); + tvKeyUsage.setText(TextUtils.join(", ", usage)); + tvKeyUsage.setVisibility(usage.isEmpty() ? View.GONE : View.VISIBLE); + tvAfter.setText(certificate.after == null ? null : TF.format(certificate.after)); tvBefore.setText(certificate.before == null ? null : TF.format(certificate.before)); tvExpired.setVisibility(certificate.isExpired() ? View.VISIBLE : View.GONE); diff --git a/app/src/main/java/eu/faircode/email/EntityCertificate.java b/app/src/main/java/eu/faircode/email/EntityCertificate.java index c98cd017f7..3754d629bc 100644 --- a/app/src/main/java/eu/faircode/email/EntityCertificate.java +++ b/app/src/main/java/eu/faircode/email/EntityCertificate.java @@ -49,6 +49,7 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.StringWriter; import java.security.NoSuchAlgorithmException; +import java.security.cert.Certificate; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; @@ -126,6 +127,47 @@ public class EntityCertificate { } } + List getKeyUsage() { + List result = new ArrayList<>(); + try { + X509Certificate cert = getCertificate(); + boolean[] usage = cert.getKeyUsage(); + if (usage == null) + return result; + if (usage.length > 0 && usage[0]) + result.add("digitalSignature"); + if (usage.length > 1 && usage[1]) + result.add("nonRepudiation"); + if (usage.length > 2 && usage[2]) + result.add("keyEncipherment"); + if (usage.length > 3 && usage[3]) + result.add("dataEncipherment"); + if (usage.length > 4 && usage[4]) + result.add("keyAgreement"); + if (usage.length > 5 && usage[5]) + result.add("keyCertSign"); + if (usage.length > 6 && usage[6]) + result.add("cRLSign"); + if (usage.length > 7 && usage[7]) + result.add("encipherOnly"); + if (usage.length > 8 && usage[8]) + result.add("decipherOnly"); + } catch (Throwable ex) { + Log.e(ex); + } + return result; + } + + Boolean isSelfSigned() { + try { + X509Certificate cert = getCertificate(); + return (cert.getIssuerX500Principal().equals(cert.getSubjectX500Principal())); + } catch (Throwable ex) { + Log.e(ex); + return null; + } + } + String getPem() throws CertificateException, IOException { StringWriter writer = new StringWriter(); JcaPEMWriter pemWriter = new JcaPEMWriter(writer); diff --git a/app/src/main/java/eu/faircode/email/FragmentMessages.java b/app/src/main/java/eu/faircode/email/FragmentMessages.java index b4157a246f..ae4f934d7c 100644 --- a/app/src/main/java/eu/faircode/email/FragmentMessages.java +++ b/app/src/main/java/eu/faircode/email/FragmentMessages.java @@ -10719,30 +10719,15 @@ public class FragmentMessages extends FragmentBase for (Certificate c : certs) try { X509Certificate cert = (X509Certificate) c; - boolean[] usage = cert.getKeyUsage(); - boolean digitalSignature = (usage != null && usage.length > 0 && usage[0]); - boolean nonRepudiation = (usage != null && usage.length > 1 && usage[1]); - boolean keyEncipherment = (usage != null && usage.length > 2 && usage[2]); - boolean dataEncipherment = (usage != null && usage.length > 3 && usage[4]); - boolean keyAgreement = (usage != null && usage.length > 4 && usage[4]); - boolean keyCertSign = (usage != null && usage.length > 5 && usage[5]); - boolean cRLSign = (usage != null && usage.length > 6 && usage[6]); - boolean encipherOnly = (usage != null && usage.length > 7 && usage[7]); - boolean decipherOnly = (usage != null && usage.length > 8 && usage[8]); - boolean selfSigned = cert.getIssuerX500Principal().equals(cert.getSubjectX500Principal()); EntityCertificate record = EntityCertificate.from(cert, null); - trace.add(record.subject + - " (" + (selfSigned ? "selfSigned" : cert.getIssuerX500Principal()) + ")" + - (digitalSignature ? " (digitalSignature)" : "") + - (nonRepudiation ? " (nonRepudiation)" : "") + - (keyEncipherment ? " (keyEncipherment)" : "") + - (dataEncipherment ? " (dataEncipherment)" : "") + - (keyAgreement ? " (keyAgreement)" : "") + - (keyCertSign ? " (keyCertSign)" : "") + - (cRLSign ? " (cRLSign)" : "") + - (encipherOnly ? " (encipherOnly)" : "") + - (decipherOnly ? " (decipherOnly)" : "") + - (ks != null && ks.getCertificateAlias(cert) != null ? " (Android)" : "")); + StringBuilder sb = new StringBuilder(); + sb.append(record.subject); + sb.append(" (").append(record.isSelfSigned() ? "selfSigned" : cert.getIssuerX500Principal()).append(")"); + for (String usage : record.getKeyUsage()) + sb.append(" (").append(usage).append(")"); + if (ks != null && ks.getCertificateAlias(cert) != null) + sb.append(" (Android)"); + trace.add(sb.toString()); } catch (Throwable ex) { Log.e(ex); trace.add(new ThrowableWrapper(ex).toSafeString()); diff --git a/app/src/main/res/layout/item_certificate.xml b/app/src/main/res/layout/item_certificate.xml index 4c3b490d01..511a43b804 100644 --- a/app/src/main/res/layout/item_certificate.xml +++ b/app/src/main/res/layout/item_certificate.xml @@ -48,6 +48,16 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/barrier" /> + + + app:layout_constraintTop_toBottomOf="@+id/tvKeyUsage" /> + app:layout_constraintTop_toBottomOf="@+id/tvKeyUsage" />