Test verifying signatures over "unusual" TBSCertificates
Test that, signatures over unusual TBSCertificates are verified
correctly. This tests that encoding is correctly round-tripped through
the parser to the verifier.
In principle, this should never happen because a DER parser will only
accept the canonical encoding of an object. However, it is possible for
encoding to not round-trip if we accept any BER inputs, or our in-memory
representation does not capture the full range of abstract
TBSCertificate values.
X509 objects cache the encoded TBSCertificate, so all encoding
variations should be captured. This test tries to exercise the cache's
effects on signature verification. In reality, the cache is barely
load-bearing. We now reject most non-DER inputs, and X509_NAME also
saves its encoding. Still, the test ensures this remains the case.
Amusingly, you're actually formally *not* supposed to do this. An X.509
signature is defined to use the DER encoding of the TBSCertificate. An
ASN.1 type is independent of the particular encoding used. If you parsed
a BER (or XER!) X.509 Certificate, you're meant to canonicalize the
encoding back to DER to verify it. As far as I know, no one does it that
way.
Change-Id: I67c4932ec87d1f6fedfc8c711cf0f7837759947e
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/81768
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
Auto-Submit: David Benjamin <davidben@google.com>
diff --git a/crypto/x509/test/make_unusual_tbs.go b/crypto/x509/test/make_unusual_tbs.go
new file mode 100644
index 0000000..eec602d
--- /dev/null
+++ b/crypto/x509/test/make_unusual_tbs.go
@@ -0,0 +1,117 @@
+// Copyright 2025 The BoringSSL Authors
+//
+// 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
+//
+// https://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.
+
+//go:build ignore
+
+// make_unusual_tbs.go refreshes the signatures on the unusual_tbs_*.pem
+// certificates.
+package main
+
+import (
+ "crypto"
+ "crypto/rand"
+ _ "crypto/sha256"
+ "crypto/x509"
+ "encoding/pem"
+ "fmt"
+ "os"
+
+ "golang.org/x/crypto/cryptobyte"
+ "golang.org/x/crypto/cryptobyte/asn1"
+)
+
+func updateSignature(path string, key crypto.Signer, opts crypto.SignerOpts) error {
+ inp, err := os.ReadFile(path)
+ if err != nil {
+ return err
+ }
+ block, _ := pem.Decode(inp)
+ if block == nil || block.Type != "CERTIFICATE" {
+ return fmt.Errorf("%q did not contain a PEM CERTIFICATE block", path)
+ }
+
+ s := cryptobyte.String(block.Bytes)
+ var cert, tbsCert, sigAlg cryptobyte.String
+ if !s.ReadASN1(&cert, asn1.SEQUENCE) ||
+ !cert.ReadASN1Element(&tbsCert, asn1.SEQUENCE) ||
+ !cert.ReadASN1Element(&sigAlg, asn1.SEQUENCE) {
+ return fmt.Errorf("could not parse certificate in %q", path)
+ }
+
+ h := opts.HashFunc().New()
+ h.Write(tbsCert)
+ digest := h.Sum(nil)
+ signature, err := key.Sign(rand.Reader, digest, opts)
+ if err != nil {
+ return err
+ }
+
+ b := cryptobyte.NewBuilder(nil)
+ b.AddASN1(asn1.SEQUENCE, func(child *cryptobyte.Builder) {
+ child.AddBytes(tbsCert)
+ child.AddBytes(sigAlg)
+ child.AddASN1BitString(signature)
+ })
+ newCert, err := b.Bytes()
+ if err != nil {
+ return err
+ }
+
+ newPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: newCert})
+ return os.WriteFile(path, newPEM, 0644)
+}
+
+func loadPEMPrivateKey(path string) (crypto.Signer, error) {
+ inp, err := os.ReadFile(path)
+ if err != nil {
+ return nil, err
+ }
+ block, _ := pem.Decode(inp)
+ if block == nil || block.Type != "PRIVATE KEY" {
+ return nil, fmt.Errorf("%q did not contain a PEM PRIVATE KEY block", path)
+ }
+ key, err := x509.ParsePKCS8PrivateKey(block.Bytes)
+ if err != nil {
+ return nil, err
+ }
+ signer, ok := key.(crypto.Signer)
+ if !ok {
+ return nil, fmt.Errorf("key in %q was not a signing key", path)
+ }
+ return signer, nil
+}
+
+func main() {
+ key, err := loadPEMPrivateKey("unusual_tbs_key.pem")
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Error loading private key: %s\n", err)
+ os.Exit(1)
+ }
+
+ paths := []string{
+ "unusual_tbs_empty_extension_not_omitted.pem",
+ "unusual_tbs_null_sigalg_param.pem",
+ "unusual_tbs_uid_both.pem",
+ "unusual_tbs_uid_issuer.pem",
+ "unusual_tbs_uid_subject.pem",
+ "unusual_tbs_wrong_attribute_order.pem",
+ "unusual_tbs_v1_not_omitted.pem",
+ }
+ for _, path := range paths {
+ if err := updateSignature(path, key, crypto.SHA256); err != nil {
+ fmt.Fprintf(os.Stderr, "Error signing %q: %s\n", path, err)
+ os.Exit(1)
+ }
+ }
+}
diff --git a/crypto/x509/test/unusual_tbs_empty_extension_not_omitted.pem b/crypto/x509/test/unusual_tbs_empty_extension_not_omitted.pem
new file mode 100644
index 0000000..d43f7ef
--- /dev/null
+++ b/crypto/x509/test/unusual_tbs_empty_extension_not_omitted.pem
@@ -0,0 +1,8 @@
+-----BEGIN CERTIFICATE-----
+MIIBFjCBvaADAgECAgkAhl+3uPLdFykwCgYIKoZIzj0EAwIwDzENMAsGA1UEAwwE
+VGVzdDAeFw0yNTA5MDIxODQzMTdaFw0yNTEwMDIxODQzMTdaMA8xDTALBgNVBAMM
+BFRlc3QwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATszjOipC1du8ay50pozmB3
+x6bHKTrwAVOMhhTg87UC2JhffDIvz2TBsePGC+aH/1oGDUs6PqR+wkjFQtSZSl3N
+owIwADAKBggqhkjOPQQDAgNIADBFAiEArzc2EQr44G4O7x1v30+5xjCr/fEwAl3I
+1dCXXsp9+9ICIBF4FtNRgfbzt6x+5wYBUGBZR1Iqsw2FIJuITa3p25TA
+-----END CERTIFICATE-----
diff --git a/crypto/x509/test/unusual_tbs_key.pem b/crypto/x509/test/unusual_tbs_key.pem
new file mode 100644
index 0000000..966dd55
--- /dev/null
+++ b/crypto/x509/test/unusual_tbs_key.pem
@@ -0,0 +1,5 @@
+-----BEGIN PRIVATE KEY-----
+MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgi4QXNrPgfmMLj/RO
+TXhG2JejJFliP8hPbMCk7kWh4HOhRANCAATszjOipC1du8ay50pozmB3x6bHKTrw
+AVOMhhTg87UC2JhffDIvz2TBsePGC+aH/1oGDUs6PqR+wkjFQtSZSl3N
+-----END PRIVATE KEY-----
diff --git a/crypto/x509/test/unusual_tbs_null_sigalg_param.pem b/crypto/x509/test/unusual_tbs_null_sigalg_param.pem
new file mode 100644
index 0000000..1c0e2bb
--- /dev/null
+++ b/crypto/x509/test/unusual_tbs_null_sigalg_param.pem
@@ -0,0 +1,8 @@
+-----BEGIN CERTIFICATE-----
+MIIBETCBtgIJAIZft7jy3RcpMAwGCCqGSM49BAMCBQAwDzENMAsGA1UEAwwEVGVz
+dDAeFw0yNTA5MDIxODQzMTdaFw0yNTEwMDIxODQzMTdaMA8xDTALBgNVBAMMBFRl
+c3QwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATszjOipC1du8ay50pozmB3x6bH
+KTrwAVOMhhTg87UC2JhffDIvz2TBsePGC+aH/1oGDUs6PqR+wkjFQtSZSl3NMAwG
+CCqGSM49BAMCBQADSAAwRQIhAJHIFuDC7wlXEfVm/tIJ3EPYAqCFF1gNFWarj7IZ
+waItAiBkpFzOXFeRV58oBXVYUe3OMCoBhUyi2Lse3qjc3nvsEQ==
+-----END CERTIFICATE-----
diff --git a/crypto/x509/test/unusual_tbs_uid_both.pem b/crypto/x509/test/unusual_tbs_uid_both.pem
new file mode 100644
index 0000000..7f7923c
--- /dev/null
+++ b/crypto/x509/test/unusual_tbs_uid_both.pem
@@ -0,0 +1,9 @@
+-----BEGIN CERTIFICATE-----
+MIIBJDCBzKADAgEBAgkAhl+3uPLdFykwCgYIKoZIzj0EAwIwDzENMAsGA1UEAwwE
+VGVzdDAeFw0yNTA5MDIxODQzMTdaFw0yNTEwMDIxODQzMTdaMA8xDTALBgNVBAMM
+BFRlc3QwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATszjOipC1du8ay50pozmB3
+x6bHKTrwAVOMhhTg87UC2JhffDIvz2TBsePGC+aH/1oGDUs6PqR+wkjFQtSZSl3N
+gQcAaXNzdWVygggAc3ViamVjdDAKBggqhkjOPQQDAgNHADBEAiA54JGXx+BJfSZN
+C6zG5i/PJ2aOFdXueTtxx44IfnTbFgIgVYpUxshFOIIk8l/wAZ9CoS8e2cQ0XKqK
+tUUzhyOXgeg=
+-----END CERTIFICATE-----
diff --git a/crypto/x509/test/unusual_tbs_uid_issuer.pem b/crypto/x509/test/unusual_tbs_uid_issuer.pem
new file mode 100644
index 0000000..8f8724b
--- /dev/null
+++ b/crypto/x509/test/unusual_tbs_uid_issuer.pem
@@ -0,0 +1,8 @@
+-----BEGIN CERTIFICATE-----
+MIIBGzCBwqADAgEBAgkAhl+3uPLdFykwCgYIKoZIzj0EAwIwDzENMAsGA1UEAwwE
+VGVzdDAeFw0yNTA5MDIxODQzMTdaFw0yNTEwMDIxODQzMTdaMA8xDTALBgNVBAMM
+BFRlc3QwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATszjOipC1du8ay50pozmB3
+x6bHKTrwAVOMhhTg87UC2JhffDIvz2TBsePGC+aH/1oGDUs6PqR+wkjFQtSZSl3N
+gQcAaXNzdWVyMAoGCCqGSM49BAMCA0gAMEUCIFpVYsgIUl2CwFSwPISEIXoHzCKG
+cjYcinUtlG3jHqPGAiEAm/jB7DE1QHlveUGc4lRHzBPvU0AthpUS/Q5XGf/hAnA=
+-----END CERTIFICATE-----
diff --git a/crypto/x509/test/unusual_tbs_uid_subject.pem b/crypto/x509/test/unusual_tbs_uid_subject.pem
new file mode 100644
index 0000000..776363a
--- /dev/null
+++ b/crypto/x509/test/unusual_tbs_uid_subject.pem
@@ -0,0 +1,8 @@
+-----BEGIN CERTIFICATE-----
+MIIBHDCBw6ADAgEBAgkAhl+3uPLdFykwCgYIKoZIzj0EAwIwDzENMAsGA1UEAwwE
+VGVzdDAeFw0yNTA5MDIxODQzMTdaFw0yNTEwMDIxODQzMTdaMA8xDTALBgNVBAMM
+BFRlc3QwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATszjOipC1du8ay50pozmB3
+x6bHKTrwAVOMhhTg87UC2JhffDIvz2TBsePGC+aH/1oGDUs6PqR+wkjFQtSZSl3N
+gggAc3ViamVjdDAKBggqhkjOPQQDAgNIADBFAiBvKz3oALhCqKrRFLUbax6+tI1s
+1B14IPVk2ZHbBEou5gIhAOpvJRNj5qluPXKLXmZvIK8uOjUhiZoowYvborSS1EBK
+-----END CERTIFICATE-----
diff --git a/crypto/x509/test/unusual_tbs_v1_not_omitted.pem b/crypto/x509/test/unusual_tbs_v1_not_omitted.pem
new file mode 100644
index 0000000..2e09028
--- /dev/null
+++ b/crypto/x509/test/unusual_tbs_v1_not_omitted.pem
@@ -0,0 +1,8 @@
+-----BEGIN CERTIFICATE-----
+MIIBETCBuaADAgEAAgkAhl+3uPLdFykwCgYIKoZIzj0EAwIwDzENMAsGA1UEAwwE
+VGVzdDAeFw0yNTA5MDIxODQzMTdaFw0yNTEwMDIxODQzMTdaMA8xDTALBgNVBAMM
+BFRlc3QwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATszjOipC1du8ay50pozmB3
+x6bHKTrwAVOMhhTg87UC2JhffDIvz2TBsePGC+aH/1oGDUs6PqR+wkjFQtSZSl3N
+MAoGCCqGSM49BAMCA0cAMEQCIF/B+SrEnMPlhmATBjKSff2d6vGeiObEhS6CQV7q
+jal2AiAFtgBo9YMcRn8jmkuuBpEjto3e9iMMk9hcbatc3MBepw==
+-----END CERTIFICATE-----
diff --git a/crypto/x509/test/unusual_tbs_wrong_attribute_order.pem b/crypto/x509/test/unusual_tbs_wrong_attribute_order.pem
new file mode 100644
index 0000000..12e9bde
--- /dev/null
+++ b/crypto/x509/test/unusual_tbs_wrong_attribute_order.pem
@@ -0,0 +1,9 @@
+-----BEGIN CERTIFICATE-----
+MIIBJjCBzgIJAIZft7jy3RcpMAoGCCqGSM49BAMCMBwxGjALBgNVBAoMBFRlc3Qw
+CwYDVQQDDARUZXN0MB4XDTI1MDkwMjE4NDMxN1oXDTI1MTAwMjE4NDMxN1owHDEa
+MAsGA1UECgwEVGVzdDALBgNVBAMMBFRlc3QwWTATBgcqhkjOPQIBBggqhkjOPQMB
+BwNCAATszjOipC1du8ay50pozmB3x6bHKTrwAVOMhhTg87UC2JhffDIvz2TBsePG
+C+aH/1oGDUs6PqR+wkjFQtSZSl3NMAoGCCqGSM49BAMCA0cAMEQCIGxfTqIwedli
+0QhOn70oL+SBnqtm9S0g73pq46AEmGFFAiAv6t930j82rFcZeud1qAqRX68kmO+q
+GOf5K70Buh5LXA==
+-----END CERTIFICATE-----
diff --git a/crypto/x509/x509_test.cc b/crypto/x509/x509_test.cc
index d76330d..7b49cdc 100644
--- a/crypto/x509/x509_test.cc
+++ b/crypto/x509/x509_test.cc
@@ -8735,4 +8735,53 @@
EXPECT_EQ(X509_REVOKED_get0_extensions(rev.get()), nullptr);
}
+// Test that, signatures over unusual TBSCertificates are verified correctly.
+// This tests that encoding is correctly round-tripped through the parser to the
+// verifier.
+//
+// In principle, this should never happen because a DER parser will only accept
+// the canonical encoding of an object. However, it is possible for encoding to
+// not round-trip if we accept any BER inputs, or our in-memory representation
+// does not capture the full range of abstract TBSCertificate values.
+//
+// |X509| objects cache the encoded TBSCertificate, so all encoding variations
+// should be captured. This test tries to exercise the cache's effects on
+// signature verification. In reality, the cache is barely load-bearing. We now
+// reject most non-DER inputs, and |X509_NAME| also saves its encoding. Still,
+// the test ensures this remains the case.
+TEST(X509Test, VerifyUnusualTBSCert) {
+ bssl::UniquePtr<EVP_PKEY> key =
+ PrivateKeyFromPEM(GetTestData("crypto/x509/test/unusual_tbs_key.pem"));
+ ASSERT_TRUE(key);
+ // The TBSCertificates were made with https://github.com/google/der-ascii.
+ // crypto/x509/test/make_unusual_tbs.go then filled in valid signatures.
+ const char *kPaths[] = {
+ // Empty extension instead of omitting the entire field.
+ // TODO(crbug.com/442221114): The parser should reject this.
+ "crypto/x509/test/unusual_tbs_empty_extension_not_omitted.pem",
+ // ecdsa-with-SHA256 AlgorithmIdentifier parameters are NULL instead of
+ // omitted. We accept this due to b/167375496.
+ "crypto/x509/test/unusual_tbs_null_sigalg_param.pem",
+ // Deprecated subject and issuer unique IDs are present. This is valid,
+ // but
+ // rarely exercised.
+ "crypto/x509/test/unusual_tbs_uid_both.pem",
+ "crypto/x509/test/unusual_tbs_uid_issuer.pem",
+ "crypto/x509/test/unusual_tbs_uid_subject.pem",
+ // Within a RelativeDistinguishedName, attributes should be sorted in
+ // canonical SET OF order. These are inverted.
+ // TODO(crbug.com/42290219): The parser should reject this.
+ "crypto/x509/test/unusual_tbs_wrong_attribute_order.pem",
+ // A v1 version is explicit encoded instead of omitted as DEFAULT.
+ // TODO(crbug.com/42290225): The parser should reject this.
+ "crypto/x509/test/unusual_tbs_v1_not_omitted.pem",
+ };
+ for (const char *path : kPaths) {
+ SCOPED_TRACE(path);
+ bssl::UniquePtr<X509> cert = CertFromPEM(GetTestData(path));
+ ASSERT_TRUE(cert);
+ EXPECT_TRUE(X509_verify(cert.get(), key.get()));
+ }
+}
+
} // namespace
diff --git a/gen/sources.bzl b/gen/sources.bzl
index 660914f..6793c33 100644
--- a/gen/sources.bzl
+++ b/gen/sources.bzl
@@ -1005,6 +1005,14 @@
"crypto/x509/test/trailing_data_leaf_name_constraints.pem",
"crypto/x509/test/trailing_data_leaf_subject_alt_name.pem",
"crypto/x509/test/trailing_data_leaf_subject_key_identifier.pem",
+ "crypto/x509/test/unusual_tbs_empty_extension_not_omitted.pem",
+ "crypto/x509/test/unusual_tbs_key.pem",
+ "crypto/x509/test/unusual_tbs_null_sigalg_param.pem",
+ "crypto/x509/test/unusual_tbs_uid_both.pem",
+ "crypto/x509/test/unusual_tbs_uid_issuer.pem",
+ "crypto/x509/test/unusual_tbs_uid_subject.pem",
+ "crypto/x509/test/unusual_tbs_v1_not_omitted.pem",
+ "crypto/x509/test/unusual_tbs_wrong_attribute_order.pem",
"third_party/wycheproof_testvectors/aes_cbc_pkcs5_test.txt",
"third_party/wycheproof_testvectors/aes_cmac_test.txt",
"third_party/wycheproof_testvectors/aes_eax_test.txt",
diff --git a/gen/sources.cmake b/gen/sources.cmake
index b3df5a8..4b73d17 100644
--- a/gen/sources.cmake
+++ b/gen/sources.cmake
@@ -1031,6 +1031,14 @@
crypto/x509/test/trailing_data_leaf_name_constraints.pem
crypto/x509/test/trailing_data_leaf_subject_alt_name.pem
crypto/x509/test/trailing_data_leaf_subject_key_identifier.pem
+ crypto/x509/test/unusual_tbs_empty_extension_not_omitted.pem
+ crypto/x509/test/unusual_tbs_key.pem
+ crypto/x509/test/unusual_tbs_null_sigalg_param.pem
+ crypto/x509/test/unusual_tbs_uid_both.pem
+ crypto/x509/test/unusual_tbs_uid_issuer.pem
+ crypto/x509/test/unusual_tbs_uid_subject.pem
+ crypto/x509/test/unusual_tbs_v1_not_omitted.pem
+ crypto/x509/test/unusual_tbs_wrong_attribute_order.pem
third_party/wycheproof_testvectors/aes_cbc_pkcs5_test.txt
third_party/wycheproof_testvectors/aes_cmac_test.txt
third_party/wycheproof_testvectors/aes_eax_test.txt
diff --git a/gen/sources.gni b/gen/sources.gni
index 703e0bd..b846755 100644
--- a/gen/sources.gni
+++ b/gen/sources.gni
@@ -1005,6 +1005,14 @@
"crypto/x509/test/trailing_data_leaf_name_constraints.pem",
"crypto/x509/test/trailing_data_leaf_subject_alt_name.pem",
"crypto/x509/test/trailing_data_leaf_subject_key_identifier.pem",
+ "crypto/x509/test/unusual_tbs_empty_extension_not_omitted.pem",
+ "crypto/x509/test/unusual_tbs_key.pem",
+ "crypto/x509/test/unusual_tbs_null_sigalg_param.pem",
+ "crypto/x509/test/unusual_tbs_uid_both.pem",
+ "crypto/x509/test/unusual_tbs_uid_issuer.pem",
+ "crypto/x509/test/unusual_tbs_uid_subject.pem",
+ "crypto/x509/test/unusual_tbs_v1_not_omitted.pem",
+ "crypto/x509/test/unusual_tbs_wrong_attribute_order.pem",
"third_party/wycheproof_testvectors/aes_cbc_pkcs5_test.txt",
"third_party/wycheproof_testvectors/aes_cmac_test.txt",
"third_party/wycheproof_testvectors/aes_eax_test.txt",
diff --git a/gen/sources.json b/gen/sources.json
index 3a6d5b0..49a26a4 100644
--- a/gen/sources.json
+++ b/gen/sources.json
@@ -985,6 +985,14 @@
"crypto/x509/test/trailing_data_leaf_name_constraints.pem",
"crypto/x509/test/trailing_data_leaf_subject_alt_name.pem",
"crypto/x509/test/trailing_data_leaf_subject_key_identifier.pem",
+ "crypto/x509/test/unusual_tbs_empty_extension_not_omitted.pem",
+ "crypto/x509/test/unusual_tbs_key.pem",
+ "crypto/x509/test/unusual_tbs_null_sigalg_param.pem",
+ "crypto/x509/test/unusual_tbs_uid_both.pem",
+ "crypto/x509/test/unusual_tbs_uid_issuer.pem",
+ "crypto/x509/test/unusual_tbs_uid_subject.pem",
+ "crypto/x509/test/unusual_tbs_v1_not_omitted.pem",
+ "crypto/x509/test/unusual_tbs_wrong_attribute_order.pem",
"third_party/wycheproof_testvectors/aes_cbc_pkcs5_test.txt",
"third_party/wycheproof_testvectors/aes_cmac_test.txt",
"third_party/wycheproof_testvectors/aes_eax_test.txt",
diff --git a/gen/sources.mk b/gen/sources.mk
index 8bda4c0..5c57c27 100644
--- a/gen/sources.mk
+++ b/gen/sources.mk
@@ -993,6 +993,14 @@
crypto/x509/test/trailing_data_leaf_name_constraints.pem \
crypto/x509/test/trailing_data_leaf_subject_alt_name.pem \
crypto/x509/test/trailing_data_leaf_subject_key_identifier.pem \
+ crypto/x509/test/unusual_tbs_empty_extension_not_omitted.pem \
+ crypto/x509/test/unusual_tbs_key.pem \
+ crypto/x509/test/unusual_tbs_null_sigalg_param.pem \
+ crypto/x509/test/unusual_tbs_uid_both.pem \
+ crypto/x509/test/unusual_tbs_uid_issuer.pem \
+ crypto/x509/test/unusual_tbs_uid_subject.pem \
+ crypto/x509/test/unusual_tbs_v1_not_omitted.pem \
+ crypto/x509/test/unusual_tbs_wrong_attribute_order.pem \
third_party/wycheproof_testvectors/aes_cbc_pkcs5_test.txt \
third_party/wycheproof_testvectors/aes_cmac_test.txt \
third_party/wycheproof_testvectors/aes_eax_test.txt \