diff options
Diffstat (limited to 'src/crypto/x509/x509_test.cc')
-rw-r--r-- | src/crypto/x509/x509_test.cc | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/src/crypto/x509/x509_test.cc b/src/crypto/x509/x509_test.cc index 9ed1b52a..bf0b29a2 100644 --- a/src/crypto/x509/x509_test.cc +++ b/src/crypto/x509/x509_test.cc @@ -1549,3 +1549,125 @@ TEST(X509Test, MismatchAlgorithms) { EXPECT_EQ(ERR_LIB_X509, ERR_GET_LIB(err)); EXPECT_EQ(X509_R_SIGNATURE_ALGORITHM_MISMATCH, ERR_GET_REASON(err)); } + +TEST(X509Test, PEMX509Info) { + std::string cert = kRootCAPEM; + auto cert_obj = CertFromPEM(kRootCAPEM); + ASSERT_TRUE(cert_obj); + + std::string rsa = kRSAKey; + auto rsa_obj = PrivateKeyFromPEM(kRSAKey); + ASSERT_TRUE(rsa_obj); + + std::string crl = kBasicCRL; + auto crl_obj = CRLFromPEM(kBasicCRL); + ASSERT_TRUE(crl_obj); + + std::string unknown = + "-----BEGIN UNKNOWN-----\n" + "AAAA\n" + "-----END UNKNOWN-----\n"; + + std::string invalid = + "-----BEGIN CERTIFICATE-----\n" + "AAAA\n" + "-----END CERTIFICATE-----\n"; + + // Each X509_INFO contains at most one certificate, CRL, etc. The format + // creates a new X509_INFO when a repeated type is seen. + std::string pem = + // The first few entries have one of everything in different orders. + cert + rsa + crl + + rsa + crl + cert + + // Unknown types are ignored. + crl + unknown + cert + rsa + + // Seeing a new certificate starts a new entry, so now we have a bunch of + // certificate-only entries. + cert + cert + cert + + // The key folds into the certificate's entry. + cert + rsa + + // Doubled keys also start new entries. + rsa + rsa + rsa + rsa + crl + + // As do CRLs. + crl + crl; + + const struct ExpectedInfo { + const X509 *cert; + const EVP_PKEY *key; + const X509_CRL *crl; + } kExpected[] = { + {cert_obj.get(), rsa_obj.get(), crl_obj.get()}, + {cert_obj.get(), rsa_obj.get(), crl_obj.get()}, + {cert_obj.get(), rsa_obj.get(), crl_obj.get()}, + {cert_obj.get(), nullptr, nullptr}, + {cert_obj.get(), nullptr, nullptr}, + {cert_obj.get(), nullptr, nullptr}, + {cert_obj.get(), rsa_obj.get(), nullptr}, + {nullptr, rsa_obj.get(), nullptr}, + {nullptr, rsa_obj.get(), nullptr}, + {nullptr, rsa_obj.get(), nullptr}, + {nullptr, rsa_obj.get(), crl_obj.get()}, + {nullptr, nullptr, crl_obj.get()}, + {nullptr, nullptr, crl_obj.get()}, + }; + + auto check_info = [](const ExpectedInfo *expected, const X509_INFO *info) { + if (expected->cert != nullptr) { + EXPECT_EQ(0, X509_cmp(expected->cert, info->x509)); + } else { + EXPECT_EQ(nullptr, info->x509); + } + if (expected->crl != nullptr) { + EXPECT_EQ(0, X509_CRL_cmp(expected->crl, info->crl)); + } else { + EXPECT_EQ(nullptr, info->crl); + } + if (expected->key != nullptr) { + ASSERT_NE(nullptr, info->x_pkey); + // EVP_PKEY_cmp returns one if the keys are equal. + EXPECT_EQ(1, EVP_PKEY_cmp(expected->key, info->x_pkey->dec_pkey)); + } else { + EXPECT_EQ(nullptr, info->x_pkey); + } + }; + + bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(pem.data(), pem.size())); + ASSERT_TRUE(bio); + bssl::UniquePtr<STACK_OF(X509_INFO)> infos( + PEM_X509_INFO_read_bio(bio.get(), nullptr, nullptr, nullptr)); + ASSERT_TRUE(infos); + ASSERT_EQ(OPENSSL_ARRAY_SIZE(kExpected), sk_X509_INFO_num(infos.get())); + for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kExpected); i++) { + SCOPED_TRACE(i); + check_info(&kExpected[i], sk_X509_INFO_value(infos.get(), i)); + } + + // Passing an existing stack appends to it. + bio.reset(BIO_new_mem_buf(pem.data(), pem.size())); + ASSERT_TRUE(bio); + ASSERT_EQ(infos.get(), + PEM_X509_INFO_read_bio(bio.get(), infos.get(), nullptr, nullptr)); + ASSERT_EQ(2 * OPENSSL_ARRAY_SIZE(kExpected), sk_X509_INFO_num(infos.get())); + for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kExpected); i++) { + SCOPED_TRACE(i); + check_info(&kExpected[i], sk_X509_INFO_value(infos.get(), i)); + check_info( + &kExpected[i], + sk_X509_INFO_value(infos.get(), i + OPENSSL_ARRAY_SIZE(kExpected))); + } + + // Gracefully handle errors in both the append and fresh cases. + std::string bad_pem = cert + cert + invalid; + + bio.reset(BIO_new_mem_buf(bad_pem.data(), bad_pem.size())); + ASSERT_TRUE(bio); + bssl::UniquePtr<STACK_OF(X509_INFO)> infos2( + PEM_X509_INFO_read_bio(bio.get(), nullptr, nullptr, nullptr)); + EXPECT_FALSE(infos2); + + bio.reset(BIO_new_mem_buf(bad_pem.data(), bad_pem.size())); + ASSERT_TRUE(bio); + EXPECT_FALSE( + PEM_X509_INFO_read_bio(bio.get(), infos.get(), nullptr, nullptr)); + EXPECT_EQ(2 * OPENSSL_ARRAY_SIZE(kExpected), sk_X509_INFO_num(infos.get())); +} |