Commit ba690cad authored by Kyle Nekritz's avatar Kyle Nekritz Committed by Facebook Github Bot

Add OpenSSLCertUtils functions for DER encoding/decoding.

Reviewed By: anirudhvr

Differential Revision: D5193205

fbshipit-source-id: 5b427ee4f31008518078f5e54e85c0f0f2201da5
parent 7dc11fbd
......@@ -173,5 +173,28 @@ std::string OpenSSLCertUtils::getDateTimeStr(const ASN1_TIME* time) {
return std::string(bioData, bioLen);
}
X509UniquePtr OpenSSLCertUtils::derDecode(ByteRange range) {
auto begin = range.data();
X509UniquePtr cert(d2i_X509(nullptr, &begin, range.size()));
if (!cert) {
throw std::runtime_error("could not read cert");
}
return cert;
}
std::unique_ptr<IOBuf> OpenSSLCertUtils::derEncode(X509& x509) {
auto len = i2d_X509(&x509, nullptr);
if (len < 0) {
throw std::runtime_error("Error computing length");
}
auto buf = IOBuf::create(len);
auto dataPtr = buf->writableData();
len = i2d_X509(&x509, &dataPtr);
if (len < 0) {
throw std::runtime_error("Error converting cert to DER");
}
buf->append(len);
return buf;
}
} // ssl
} // folly
......@@ -19,7 +19,9 @@
#include <vector>
#include <folly/Optional.h>
#include <folly/io/IOBuf.h>
#include <folly/portability/OpenSSL.h>
#include <folly/ssl/OpenSSLPtrTypes.h>
namespace folly {
namespace ssl {
......@@ -60,6 +62,20 @@ class OpenSSLCertUtils {
*/
static folly::Optional<std::string> toString(X509& x509);
/**
* Decodes the DER representation of an X509 certificate.
*
* Throws on error (if a valid certificate can't be decoded).
*/
static X509UniquePtr derDecode(ByteRange);
/**
* DER encodes an X509 certificate.
*
* Throws on error.
*/
static std::unique_ptr<IOBuf> derEncode(X509&);
private:
static std::string getDateTimeStr(const ASN1_TIME* time);
};
......
......@@ -18,9 +18,10 @@
#include <folly/Range.h>
#include <folly/String.h>
#include <folly/ssl/OpenSSLPtrTypes.h>
#include <folly/io/async/SSLContext.h>
#include <folly/portability/GTest.h>
#include <folly/portability/OpenSSL.h>
#include <folly/ssl/OpenSSLPtrTypes.h>
using namespace testing;
using namespace folly;
......@@ -56,6 +57,13 @@ const std::string kTestCertWithSan = folly::stripLeftMargin(R"(
-----END CERTIFICATE-----
)");
class OpenSSLCertUtilsTest : public Test {
public:
void SetUp() override {
SSLContext::initializeOpenSSL();
}
};
static folly::ssl::X509UniquePtr readCertFromFile(const std::string& filename) {
folly::ssl::BioUniquePtr bio(BIO_new(BIO_s_file()));
if (!bio) {
......@@ -79,9 +87,7 @@ static folly::ssl::X509UniquePtr readCertFromData(
PEM_read_bio_X509(bio.get(), nullptr, nullptr, nullptr));
}
TEST(OpenSSLCertUtilsTest, TestX509CN) {
OpenSSL_add_all_algorithms();
TEST_F(OpenSSLCertUtilsTest, TestX509CN) {
auto x509 = readCertFromFile(kTestCertWithoutSan);
EXPECT_NE(x509, nullptr);
auto identity = folly::ssl::OpenSSLCertUtils::getCommonName(*x509);
......@@ -90,9 +96,7 @@ TEST(OpenSSLCertUtilsTest, TestX509CN) {
EXPECT_EQ(sans.size(), 0);
}
TEST(OpenSSLCertUtilsTest, TestX509Sans) {
OpenSSL_add_all_algorithms();
TEST_F(OpenSSLCertUtilsTest, TestX509Sans) {
auto x509 = readCertFromData(kTestCertWithSan);
EXPECT_NE(x509, nullptr);
auto identity = folly::ssl::OpenSSLCertUtils::getCommonName(*x509);
......@@ -103,9 +107,7 @@ TEST(OpenSSLCertUtilsTest, TestX509Sans) {
EXPECT_EQ(altNames[1], "*.thirdexample.com");
}
TEST(OpenSSLCertUtilsTest, TestX509IssuerAndSubject) {
OpenSSL_add_all_algorithms();
TEST_F(OpenSSLCertUtilsTest, TestX509IssuerAndSubject) {
auto x509 = readCertFromData(kTestCertWithSan);
EXPECT_NE(x509, nullptr);
auto issuer = folly::ssl::OpenSSLCertUtils::getIssuer(*x509);
......@@ -116,9 +118,7 @@ TEST(OpenSSLCertUtilsTest, TestX509IssuerAndSubject) {
EXPECT_EQ(subj.value(), "C = US, O = Asox, CN = 127.0.0.1");
}
TEST(OpenSSLCertUtilsTest, TestX509Dates) {
OpenSSL_add_all_algorithms();
TEST_F(OpenSSLCertUtilsTest, TestX509Dates) {
auto x509 = readCertFromData(kTestCertWithSan);
EXPECT_NE(x509, nullptr);
auto notBefore = folly::ssl::OpenSSLCertUtils::getNotBeforeTime(*x509);
......@@ -127,9 +127,7 @@ TEST(OpenSSLCertUtilsTest, TestX509Dates) {
EXPECT_EQ(notAfter, "Jul 1 23:21:03 2044 GMT");
}
TEST(OpenSSLCertUtilsTest, TestX509Summary) {
OpenSSL_add_all_algorithms();
TEST_F(OpenSSLCertUtilsTest, TestX509Summary) {
auto x509 = readCertFromData(kTestCertWithSan);
EXPECT_NE(x509, nullptr);
auto summary = folly::ssl::OpenSSLCertUtils::toString(*x509);
......@@ -154,3 +152,30 @@ TEST(OpenSSLCertUtilsTest, TestX509Summary) {
" Authority Information Access: \n"
" CA Issuers - URI:https://phabricator.fb.com/diffusion/FBCODE/browse/master/ti/test_certs/ca_cert.pem?view=raw\n\n");
}
TEST_F(OpenSSLCertUtilsTest, TestDerEncodeDecode) {
auto x509 = readCertFromData(kTestCertWithSan);
auto der = folly::ssl::OpenSSLCertUtils::derEncode(*x509);
auto decoded = folly::ssl::OpenSSLCertUtils::derDecode(der->coalesce());
EXPECT_EQ(
folly::ssl::OpenSSLCertUtils::toString(*x509),
folly::ssl::OpenSSLCertUtils::toString(*decoded));
}
TEST_F(OpenSSLCertUtilsTest, TestDerDecodeJunkData) {
StringPiece junk{"MyFakeCertificate"};
EXPECT_THROW(
folly::ssl::OpenSSLCertUtils::derDecode(junk), std::runtime_error);
}
TEST_F(OpenSSLCertUtilsTest, TestDerDecodeTooShort) {
auto x509 = readCertFromData(kTestCertWithSan);
auto der = folly::ssl::OpenSSLCertUtils::derEncode(*x509);
der->trimEnd(1);
EXPECT_THROW(
folly::ssl::OpenSSLCertUtils::derDecode(der->coalesce()),
std::runtime_error);
}
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