Accept only digital signature key usage for RCS-MLS

The leaf is only supposed to have one bit set, and
it must be Digital Signature

Bug: 394613330
Change-Id: Iefef4cbf7301f72ac2e797c9a65ff3046be39b92
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/77309
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: Bob Beck <bbe@google.com>
diff --git a/pki/common_cert_errors.cc b/pki/common_cert_errors.cc
index af36eca..edf7daf 100644
--- a/pki/common_cert_errors.cc
+++ b/pki/common_cert_errors.cc
@@ -30,6 +30,9 @@
 DEFINE_CERT_ERROR_ID(kUnconsumedCriticalExtension,
                      "Unconsumed critical extension");
 DEFINE_CERT_ERROR_ID(kKeyCertSignBitNotSet, "keyCertSign bit is not set");
+DEFINE_CERT_ERROR_ID(kKeyUsageIncorrectForRcsMlsClient,
+                     "KeyUsage must have only the digitalSignature bit set for "
+                     "rcsMlsClient auth");
 DEFINE_CERT_ERROR_ID(kMaxPathLengthViolated, "max_path_length reached");
 DEFINE_CERT_ERROR_ID(kBasicConstraintsIndicatesNotCa,
                      "Basic Constraints indicates not a CA");
diff --git a/pki/common_cert_errors.h b/pki/common_cert_errors.h
index 5b7a871..f8db8df 100644
--- a/pki/common_cert_errors.h
+++ b/pki/common_cert_errors.h
@@ -58,6 +58,10 @@
 // keyCertSign KeyUsage was not set.
 OPENSSL_EXPORT extern const CertErrorId kKeyCertSignBitNotSet;
 
+// The certificate is being used for RCS MLS but the required digitalSignature
+// bit was either not set, or was not the only bit set.
+OPENSSL_EXPORT extern const CertErrorId kKeyUsageIncorrectForRcsMlsClient;
+
 // The chain violates the max_path_length from BasicConstraints.
 OPENSSL_EXPORT extern const CertErrorId kMaxPathLengthViolated;
 
diff --git a/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth-extra/chain.pem b/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth-extra/chain.pem
index 1a7bdf8..fcbc08e 100644
--- a/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth-extra/chain.pem
+++ b/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth-extra/chain.pem
@@ -1,13 +1,13 @@
 -----BEGIN CERTIFICATE-----
-MIIBkDCCATagAwIBAgIBAzAKBggqhkjOPQQDAjAgMR4wHAYDVQQDExVNTFMgQ2Vy
+MIIBjDCCATOgAwIBAgIBAzAKBggqhkjOPQQDAjAgMR4wHAYDVQQDExVNTFMgQ2Vy
 dCBJbnRlcm1lZGlhdGUwIhgPMDAwMDAxMDEwMDAwMDBaGA85OTk5MTIzMTIzNTk1
 OVowGDEWMBQGA1UEAxMNTUxTIENlcnQgTGVhZjBZMBMGByqGSM49AgEGCCqGSM49
 AwEHA0IABJEq2LxVbZGSZr4q32NCQw2K2UKzSXnDy7dJLCbsdlES+ZwEIkGNUhER
-pxGojS6aHNHZXk0vMEE/3I8P8D4KHlejZTBjMA4GA1UdDwEB/wQEAwIHgDAMBgNV
-HRMBAf8EAjAAMA0GA1UdDgQGBARsZWFmMBcGA1UdIwQQMA6ADGludGVybWVkaWF0
-ZTAbBgNVHSUEFDASBgZngRICAQMGCCsGAQUFBwMCMAoGCCqGSM49BAMCA0gAMEUC
-ICZ2aFiHqdwrk44duDdK3KB/j3o2KNsILy0kSrOL85x9AiEA19Xas5gJfMK02neq
-UCzUZsXgFZDdfQdg05qikpSox1o=
+pxGojS6aHNHZXk0vMEE/3I8P8D4KHlejYjBgMA4GA1UdDwEB/wQEAwIFoDAYBgNV
+HSUEETAPBgZngRICAQMGBWeBBQgBMAwGA1UdEwEB/wQCMAAwDQYDVR0OBAYEBGxl
+YWYwFwYDVR0jBBAwDoAMaW50ZXJtZWRpYXRlMAoGCCqGSM49BAMCA0cAMEQCIBPZ
+e8YKCfB9njvqxscvNyXD9x+9oZvwGZ+yiudo1WFWAiB395X3vB8qc9sxVmuWMM8d
+kHjKKyiamynH40DPyKgvjw==
 -----END CERTIFICATE-----
 -----BEGIN CERTIFICATE-----
 MIIBkzCCATmgAwIBAgIBAjAKBggqhkjOPQQDAjAYMRYwFAYDVQQDEw1NTFMgQ2Vy
diff --git a/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth-extra/mlsclientauth.test b/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth-extra/mlsclientauth.test
index 82d223f..db097f6 100644
--- a/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth-extra/mlsclientauth.test
+++ b/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth-extra/mlsclientauth.test
@@ -4,6 +4,7 @@
 key_purpose: MLS_CLIENT_AUTH
 expected_errors:
 ----- Certificate i=0 (CN=MLS Cert Leaf) -----
+ERROR: KeyUsage must have only the digitalSignature bit set for rcsMlsClient auth
 ERROR: The extended key usage does not contain only the rcsMlsClient key purpose.
 
 ----- Certificate i=1 (CN=MLS Cert Intermediate) -----
diff --git a/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/make-mls-extensions.go b/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/make-mls-extensions.go
index 3d9f65a..2b73624 100644
--- a/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/make-mls-extensions.go
+++ b/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/make-mls-extensions.go
@@ -125,6 +125,7 @@
 	leafInvalid := leaf
 	leafInvalid.template.UnknownExtKeyUsage = []asn1.ObjectIdentifier{[]int{2, 23, 146, 2, 1, 3},
 		[]int{2, 23, 133, 8, 1}}
+	leafInvalid.template.KeyUsage |= x509.KeyUsageKeyEncipherment
 	mustGenerateCertificate("mls_client_leaf_extra_eku.pem", &leafInvalid, &intermediateInvalid)
 }
 
diff --git a/pki/testdata/verify_certificate_chain_unittest/target-eku-any/mlsclientauth.test b/pki/testdata/verify_certificate_chain_unittest/target-eku-any/mlsclientauth.test
index 57f822e..8ce80de 100644
--- a/pki/testdata/verify_certificate_chain_unittest/target-eku-any/mlsclientauth.test
+++ b/pki/testdata/verify_certificate_chain_unittest/target-eku-any/mlsclientauth.test
@@ -4,6 +4,7 @@
 key_purpose: MLS_CLIENT_AUTH
 expected_errors:
 ----- Certificate i=0 (CN=Target) -----
+ERROR: KeyUsage must have only the digitalSignature bit set for rcsMlsClient auth
 ERROR: The extended key usage does not contain only the rcsMlsClient key purpose.
 
 ----- Certificate i=1 (CN=Intermediate) -----
diff --git a/pki/testdata/verify_certificate_chain_unittest/target-eku-many/mlsclientauth.test b/pki/testdata/verify_certificate_chain_unittest/target-eku-many/mlsclientauth.test
index 57f822e..8ce80de 100644
--- a/pki/testdata/verify_certificate_chain_unittest/target-eku-many/mlsclientauth.test
+++ b/pki/testdata/verify_certificate_chain_unittest/target-eku-many/mlsclientauth.test
@@ -4,6 +4,7 @@
 key_purpose: MLS_CLIENT_AUTH
 expected_errors:
 ----- Certificate i=0 (CN=Target) -----
+ERROR: KeyUsage must have only the digitalSignature bit set for rcsMlsClient auth
 ERROR: The extended key usage does not contain only the rcsMlsClient key purpose.
 
 ----- Certificate i=1 (CN=Intermediate) -----
diff --git a/pki/testdata/verify_certificate_chain_unittest/target-eku-none/mlsclientauth.test b/pki/testdata/verify_certificate_chain_unittest/target-eku-none/mlsclientauth.test
index 52d1446..c34bd13 100644
--- a/pki/testdata/verify_certificate_chain_unittest/target-eku-none/mlsclientauth.test
+++ b/pki/testdata/verify_certificate_chain_unittest/target-eku-none/mlsclientauth.test
@@ -4,6 +4,7 @@
 key_purpose: MLS_CLIENT_AUTH
 expected_errors:
 ----- Certificate i=0 (CN=Target) -----
+ERROR: KeyUsage must have only the digitalSignature bit set for rcsMlsClient auth
 ERROR: Certificate does not have extended key usage
 
 ----- Certificate i=1 (CN=Intermediate) -----
diff --git a/pki/verify_certificate_chain.cc b/pki/verify_certificate_chain.cc
index 219273f..0e45373 100644
--- a/pki/verify_certificate_chain.cc
+++ b/pki/verify_certificate_chain.cc
@@ -246,6 +246,17 @@
   }
 
   if (required_key_purpose == KeyPurpose::RCS_MLS_CLIENT_AUTH) {
+    // Enforce the key usage restriction for a leaf from section A.3.8.3 here
+    // as well.
+    if (is_target_cert &&
+        (!cert.has_key_usage() ||
+         // This works to enforce that digital signature is the only bit because
+         // digital signature is bit 0.
+         !cert.key_usage().AssertsBit(KEY_USAGE_BIT_DIGITAL_SIGNATURE) ||
+         cert.key_usage().bytes().size() != 1 ||
+         cert.key_usage().unused_bits() != 7)) {
+      errors->AddError(cert_errors::kKeyUsageIncorrectForRcsMlsClient);
+    }
     // Rules for MLS client auth. For the leaf and all intermediates, EKU must
     // be present and have exactly one EKU which is rcsMlsClient.
     if (!cert.has_extended_key_usage()) {