From: Neel Goyal Date: Fri, 5 Jan 2018 01:56:20 +0000 (-0800) Subject: Add utility to create stores X-Git-Tag: v2018.01.08.00~14 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=79c30edd275d3f2b17c56c1194cc330489593b75;p=folly.git Add utility to create stores Summary: Add methods to create a X509StoreUniquePtr from a ca file or buffer. Reviewed By: yfeldblum Differential Revision: D6662538 fbshipit-source-id: 646f61596f2787756b2fa5998a43f36d75a91d90 --- diff --git a/folly/ssl/OpenSSLCertUtils.cpp b/folly/ssl/OpenSSLCertUtils.cpp index ac7cd741..f07096d2 100644 --- a/folly/ssl/OpenSSLCertUtils.cpp +++ b/folly/ssl/OpenSSLCertUtils.cpp @@ -15,6 +15,7 @@ */ #include +#include #include #include #include @@ -240,6 +241,32 @@ std::array OpenSSLCertUtils::getDigestSha256( return md; } +X509StoreUniquePtr OpenSSLCertUtils::readStoreFromFile(std::string caFile) { + std::string certData; + if (!folly::readFile(caFile.c_str(), certData)) { + throw std::runtime_error( + folly::to("Could not read store file: ", caFile)); + } + auto certRange = folly::ByteRange(folly::StringPiece(certData)); + return readStoreFromBuffer(std::move(certRange)); +} +X509StoreUniquePtr OpenSSLCertUtils::readStoreFromBuffer(ByteRange certRange) { + auto certs = readCertsFromBuffer(certRange); + ERR_clear_error(); + folly::ssl::X509StoreUniquePtr store(X509_STORE_new()); + for (auto& caCert : certs) { + if (X509_STORE_add_cert(store.get(), caCert.get()) != 1) { + auto err = ERR_get_error(); + if (ERR_GET_LIB(err) != ERR_LIB_X509 || + ERR_GET_REASON(err) != X509_R_CERT_ALREADY_IN_HASH_TABLE) { + throw std::runtime_error(folly::to( + "Could not insert CA certificate into store: ", + std::string(ERR_error_string(err, nullptr)))); + } + } + } + return store; +} } // namespace ssl } // namespace folly diff --git a/folly/ssl/OpenSSLCertUtils.h b/folly/ssl/OpenSSLCertUtils.h index 31273d02..edf3498c 100644 --- a/folly/ssl/OpenSSLCertUtils.h +++ b/folly/ssl/OpenSSLCertUtils.h @@ -1,5 +1,5 @@ /* - * Copyright 2017 Facebook, Inc. + * Copyright 2017-present Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -90,6 +90,12 @@ class OpenSSLCertUtils { static std::array getDigestSha1(X509& x509); static std::array getDigestSha256(X509& x509); + /** + * Reads a store from a file (or buffer). Throws on error. + */ + static X509StoreUniquePtr readStoreFromFile(std::string caFile); + static X509StoreUniquePtr readStoreFromBuffer(ByteRange); + private: static std::string getDateTimeStr(const ASN1_TIME* time); }; diff --git a/folly/ssl/test/OpenSSLCertUtilsTest.cpp b/folly/ssl/test/OpenSSLCertUtilsTest.cpp index ac747b33..de4f40fd 100644 --- a/folly/ssl/test/OpenSSLCertUtilsTest.cpp +++ b/folly/ssl/test/OpenSSLCertUtilsTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2017 Facebook, Inc. + * Copyright 2017-present Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - #include #include @@ -29,6 +28,7 @@ using namespace testing; using namespace folly; const char* kTestCertWithoutSan = "folly/io/async/test/certs/tests-cert.pem"; +const char* kTestCa = "folly/io/async/test/certs/ca-cert.pem"; // Test key // -----BEGIN EC PRIVATE KEY----- @@ -273,3 +273,15 @@ TEST_F(OpenSSLCertUtilsTest, TestX509Digest) { folly::hexlify(folly::range(sha2Digest)), "364d3a6a0b10d0635ce59b40c0b7f505ab2cd9fd0a06661cdc61d9cb8c9c9821"); } + +TEST_F(OpenSSLCertUtilsTest, TestX509Store) { + auto store = folly::ssl::OpenSSLCertUtils::readStoreFromFile(kTestCa); + EXPECT_NE(store, nullptr); + + auto x509 = readCertFromFile(kTestCertWithoutSan); + folly::ssl::X509StoreCtxUniquePtr ctx(X509_STORE_CTX_new()); + auto rc = X509_STORE_CTX_init(ctx.get(), store.get(), x509.get(), nullptr); + EXPECT_EQ(rc, 1); + rc = X509_verify_cert(ctx.get()); + EXPECT_EQ(rc, 1); +}