diff --git a/app/src/main/java/eu/faircode/email/FragmentCompose.java b/app/src/main/java/eu/faircode/email/FragmentCompose.java
index 43ed7be1dd..a5a4b67aac 100644
--- a/app/src/main/java/eu/faircode/email/FragmentCompose.java
+++ b/app/src/main/java/eu/faircode/email/FragmentCompose.java
@@ -4388,6 +4388,7 @@ public class FragmentCompose extends FragmentBase {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
boolean check_certificate = prefs.getBoolean("check_certificate", true);
+ boolean check_key_usage = prefs.getBoolean("check_key_usage", false);
File tmp = Helper.ensureExists(context, "encryption");
@@ -4455,8 +4456,30 @@ public class FragmentCompose extends FragmentBase {
// Check public key validity
try {
chain[0].checkValidity();
- // TODO: check digitalSignature/nonRepudiation key usage
- // https://datatracker.ietf.org/doc/html/rfc3850#section-4.4.2
+
+ if (check_key_usage) {
+ // Signing Key: Key Usage: Digital Signature, Non-Repudiation
+ // Encrypting Key: Key Usage: Key Encipherment, Data Encipherment
+
+ boolean[] usage = chain[0].getKeyUsage();
+ if (usage != null && usage.length > 3) {
+ // https://datatracker.ietf.org/doc/html/rfc3280#section-4.2.1.3
+ // https://datatracker.ietf.org/doc/html/rfc3850#section-4.4.2
+ boolean digitalSignature = usage[0];
+ boolean keyEncipherment = usage[2];
+
+ if (EntityMessage.SMIME_SIGNONLY.equals(type)) {
+ if (!digitalSignature)
+ throw new IllegalAccessException("Invalid key usage:" +
+ " digitalSignature=" + digitalSignature);
+ } else if (EntityMessage.SMIME_SIGNENCRYPT.equals(type)) {
+ if (!digitalSignature || !keyEncipherment)
+ throw new IllegalAccessException("Invalid key usage:" +
+ " digitalSignature=" + digitalSignature +
+ " keyEncipherment=" + keyEncipherment);
+ }
+ }
+ }
} catch (CertificateException ex) {
String msg = ex.getMessage();
throw new IllegalArgumentException(
diff --git a/app/src/main/java/eu/faircode/email/FragmentOptionsEncryption.java b/app/src/main/java/eu/faircode/email/FragmentOptionsEncryption.java
index 9a0d0053c0..54852983de 100644
--- a/app/src/main/java/eu/faircode/email/FragmentOptionsEncryption.java
+++ b/app/src/main/java/eu/faircode/email/FragmentOptionsEncryption.java
@@ -105,6 +105,7 @@ public class FragmentOptionsEncryption extends FragmentBase
private Spinner spSignAlgoSmime;
private Spinner spEncryptAlgoSmime;
private SwitchCompat swCheckCertificate;
+ private SwitchCompat swCheckKeyUsage;
private Button btnManageCertificates;
private Button btnImportKey;
private Button btnManageKeys;
@@ -123,7 +124,7 @@ public class FragmentOptionsEncryption extends FragmentBase
"sign_default", "encrypt_default", "encrypt_auto", "encrypt_reply",
"auto_verify", "auto_decrypt", "auto_undecrypt",
"openpgp_provider", "autocrypt", "autocrypt_mutual", "encrypt_subject",
- "sign_algo_smime", "encrypt_algo_smime", "check_certificate"
+ "sign_algo_smime", "encrypt_algo_smime", "check_certificate", "check_key_usage"
));
@Override
@@ -159,6 +160,7 @@ public class FragmentOptionsEncryption extends FragmentBase
spSignAlgoSmime = view.findViewById(R.id.spSignAlgoSmime);
spEncryptAlgoSmime = view.findViewById(R.id.spEncryptAlgoSmime);
swCheckCertificate = view.findViewById(R.id.swCheckCertificate);
+ swCheckKeyUsage = view.findViewById(R.id.swCheckKeyUsage);
btnManageCertificates = view.findViewById(R.id.btnManageCertificates);
btnImportKey = view.findViewById(R.id.btnImportKey);
btnManageKeys = view.findViewById(R.id.btnManageKeys);
@@ -395,6 +397,14 @@ public class FragmentOptionsEncryption extends FragmentBase
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
prefs.edit().putBoolean("check_certificate", checked).apply();
+ swCheckKeyUsage.setEnabled(checked);
+ }
+ });
+
+ swCheckKeyUsage.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
+ prefs.edit().putBoolean("check_key_usage", checked).apply();
}
});
@@ -709,6 +719,8 @@ public class FragmentOptionsEncryption extends FragmentBase
}
swCheckCertificate.setChecked(prefs.getBoolean("check_certificate", true));
+ swCheckKeyUsage.setChecked(prefs.getBoolean("check_key_usage", false));
+ swCheckKeyUsage.setEnabled(swCheckCertificate.isChecked());
} catch (Throwable ex) {
Log.e(ex);
}
diff --git a/app/src/main/res/layout/fragment_options_encryption.xml b/app/src/main/res/layout/fragment_options_encryption.xml
index 4378a65bb3..f9037588f2 100644
--- a/app/src/main/res/layout/fragment_options_encryption.xml
+++ b/app/src/main/res/layout/fragment_options_encryption.xml
@@ -421,6 +421,19 @@
app:layout_constraintTop_toBottomOf="@id/tvAlgoHint"
app:switchPadding="12dp" />
+
+
+ app:layout_constraintTop_toBottomOf="@id/swCheckKeyUsage" />