Commit 79c30edd authored by Neel Goyal's avatar Neel Goyal Committed by Facebook Github Bot

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
parent c60784b8
......@@ -15,6 +15,7 @@
*/
#include <folly/ssl/OpenSSLCertUtils.h>
#include <folly/FileUtil.h>
#include <folly/ScopeGuard.h>
#include <folly/String.h>
#include <folly/ssl/OpenSSLPtrTypes.h>
......@@ -240,6 +241,32 @@ std::array<uint8_t, SHA256_DIGEST_LENGTH> 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<std::string>("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<std::string>(
"Could not insert CA certificate into store: ",
std::string(ERR_error_string(err, nullptr))));
}
}
}
return store;
}
} // namespace ssl
} // namespace folly
/*
* 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<uint8_t, SHA_DIGEST_LENGTH> getDigestSha1(X509& x509);
static std::array<uint8_t, SHA256_DIGEST_LENGTH> 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);
};
......
/*
* 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 <folly/ssl/OpenSSLCertUtils.h>
#include <folly/Format.h>
......@@ -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);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment