proxygen
folly::ssl::OpenSSLCertUtils Class Reference

#include <OpenSSLCertUtils.h>

Static Public Member Functions

static Optional< std::stringgetCommonName (X509 &x509)
 
static std::vector< std::stringgetSubjectAltNames (X509 &x509)
 
static Optional< std::stringgetSubject (X509 &x509)
 
static Optional< std::stringgetIssuer (X509 &x509)
 
static std::string getNotBeforeTime (X509 &x509)
 
static std::string getNotAfterTime (X509 &x509)
 
static folly::Optional< std::stringtoString (X509 &x509)
 
static X509UniquePtr derDecode (ByteRange)
 
static std::unique_ptr< IOBufderEncode (X509 &)
 
static std::vector< X509UniquePtrreadCertsFromBuffer (ByteRange range)
 
static std::array< uint8_t, SHA_DIGEST_LENGTH > getDigestSha1 (X509 &x509)
 
static std::array< uint8_t, SHA256_DIGEST_LENGTH > getDigestSha256 (X509 &x509)
 
static X509StoreUniquePtr readStoreFromFile (std::string caFile)
 
static X509StoreUniquePtr readStoreFromBuffer (ByteRange range)
 

Static Private Member Functions

static std::string getDateTimeStr (const ASN1_TIME *time)
 

Detailed Description

Definition at line 29 of file OpenSSLCertUtils.h.

Member Function Documentation

X509UniquePtr folly::ssl::OpenSSLCertUtils::derDecode ( ByteRange  range)
static

Decode the DER representation of an X509 certificate.

Throws on error (if a valid certificate can't be decoded).

Definition at line 185 of file OpenSSLCertUtils.cpp.

References folly::test::begin(), folly::Range< Iter >::data(), and folly::Range< Iter >::size().

Referenced by TEST_P().

185  {
186  auto begin = range.data();
187  X509UniquePtr cert(d2i_X509(nullptr, &begin, range.size()));
188  if (!cert) {
189  throw std::runtime_error("could not read cert");
190  }
191  return cert;
192 }
std::unique_ptr< X509, X509Deleter > X509UniquePtr
auto begin(TestAdlIterable &instance)
Definition: ForeachTest.cpp:56
constexpr Range< Iter > range(Iter first, Iter last)
Definition: Range.h:1114
std::unique_ptr< IOBuf > folly::ssl::OpenSSLCertUtils::derEncode ( X509 &  x509)
static

Encode an X509 certificate in DER format.

Throws on error.

Definition at line 194 of file OpenSSLCertUtils.cpp.

References folly::IOBuf::create(), and dataPtr().

Referenced by fizz::server::appendClientCertificate(), fizz::test::getCertData(), and TEST_P().

194  {
195  auto len = i2d_X509(&x509, nullptr);
196  if (len < 0) {
197  throw std::runtime_error("Error computing length");
198  }
199  auto buf = IOBuf::create(len);
200  auto dataPtr = buf->writableData();
201  len = i2d_X509(&x509, &dataPtr);
202  if (len < 0) {
203  throw std::runtime_error("Error converting cert to DER");
204  }
205  buf->append(len);
206  return buf;
207 }
static std::unique_ptr< IOBuf > create(std::size_t capacity)
Definition: IOBuf.cpp:229
Container::value_type * dataPtr(Container &cont)
Definition: RangeTest.cpp:1082
Optional< std::string > folly::ssl::OpenSSLCertUtils::getCommonName ( X509 &  x509)
static

Definition at line 34 of file OpenSSLCertUtils.cpp.

References folly::portability::ssl::ASN1_STRING_get0_data(), folly::none, and string.

Referenced by ConnectionFilterTest::createDefaultOpts(), fizz::SelfCertImpl< T >::getIdentity(), fizz::PeerCertImpl< T >::getIdentity(), TestHandlerFactory::TestHandler::onEOM(), TEST_P(), validateTestCertBundle(), and validateTestCertWithSAN().

34  {
35  auto subject = X509_get_subject_name(&x509);
36  if (!subject) {
37  return none;
38  }
39 
40  auto cnLoc = X509_NAME_get_index_by_NID(subject, NID_commonName, -1);
41  if (cnLoc < 0) {
42  return none;
43  }
44 
45  auto cnEntry = X509_NAME_get_entry(subject, cnLoc);
46  if (!cnEntry) {
47  return none;
48  }
49 
50  auto cnAsn = X509_NAME_ENTRY_get_data(cnEntry);
51  if (!cnAsn) {
52  return none;
53  }
54 
55  auto cnData = reinterpret_cast<const char*>(ASN1_STRING_get0_data(cnAsn));
56  auto cnLen = ASN1_STRING_length(cnAsn);
57  if (!cnData || cnLen <= 0) {
58  return none;
59  }
60 
61  return Optional<std::string>(std::string(cnData, cnLen));
62 }
unsigned char * ASN1_STRING_get0_data(const ASN1_STRING *x)
Definition: OpenSSL.cpp:199
const char * string
Definition: Conv.cpp:212
constexpr None none
Definition: Optional.h:87
std::string folly::ssl::OpenSSLCertUtils::getDateTimeStr ( const ASN1_TIME *  time)
staticprivate

Definition at line 166 of file OpenSSLCertUtils.cpp.

References string, and folly::detail::distributed_mutex::time().

Referenced by getNotAfterTime(), and getNotBeforeTime().

166  {
167  if (!time) {
168  return "";
169  }
170 
171  auto bio = BioUniquePtr(BIO_new(BIO_s_mem()));
172  if (bio == nullptr) {
173  throw std::runtime_error("Cannot allocate bio");
174  }
175 
176  if (ASN1_TIME_print(bio.get(), time) <= 0) {
177  throw std::runtime_error("Cannot print ASN1_TIME");
178  }
179 
180  char* bioData = nullptr;
181  size_t bioLen = BIO_get_mem_data(bio.get(), &bioData);
182  return std::string(bioData, bioLen);
183 }
std::unique_ptr< BIO, BioDeleter > BioUniquePtr
const char * string
Definition: Conv.cpp:212
std::chrono::nanoseconds time()
std::array< uint8_t, SHA_DIGEST_LENGTH > folly::ssl::OpenSSLCertUtils::getDigestSha1 ( X509 &  x509)
static

Return the output of the X509_digest for chosen message-digest algo NOTE: The returned digest will be in binary, and may need to be hex-encoded

Definition at line 240 of file OpenSSLCertUtils.cpp.

Referenced by TEST_P().

241  {
242  unsigned int len;
243  std::array<uint8_t, SHA_DIGEST_LENGTH> md;
244  int rc = X509_digest(&x509, EVP_sha1(), md.data(), &len);
245 
246  if (rc <= 0) {
247  throw std::runtime_error("Could not calculate SHA1 digest for cert");
248  }
249  return md;
250 }
std::array< uint8_t, SHA256_DIGEST_LENGTH > folly::ssl::OpenSSLCertUtils::getDigestSha256 ( X509 &  x509)
static

Definition at line 252 of file OpenSSLCertUtils.cpp.

Referenced by TEST_P().

253  {
254  unsigned int len;
255  std::array<uint8_t, SHA256_DIGEST_LENGTH> md;
256  int rc = X509_digest(&x509, EVP_sha256(), md.data(), &len);
257 
258  if (rc <= 0) {
259  throw std::runtime_error("Could not calculate SHA256 digest for cert");
260  }
261  return md;
262 }
Optional< std::string > folly::ssl::OpenSSLCertUtils::getIssuer ( X509 &  x509)
static

Definition at line 111 of file OpenSSLCertUtils.cpp.

References folly::none, and string.

Referenced by TEST_P().

111  {
112  auto issuer = X509_get_issuer_name(&x509);
113  if (!issuer) {
114  return none;
115  }
116 
117  auto bio = BioUniquePtr(BIO_new(BIO_s_mem()));
118  if (bio == nullptr) {
119  throw std::runtime_error("Cannot allocate bio");
120  }
121 
122  if (X509_NAME_print_ex(bio.get(), issuer, 0, XN_FLAG_ONELINE) <= 0) {
123  return none;
124  }
125 
126  char* bioData = nullptr;
127  size_t bioLen = BIO_get_mem_data(bio.get(), &bioData);
128  return std::string(bioData, bioLen);
129 }
std::unique_ptr< BIO, BioDeleter > BioUniquePtr
const char * string
Definition: Conv.cpp:212
constexpr None none
Definition: Optional.h:87
std::string folly::ssl::OpenSSLCertUtils::getNotAfterTime ( X509 &  x509)
static

Definition at line 158 of file OpenSSLCertUtils.cpp.

References getDateTimeStr().

Referenced by TEST_P().

158  {
159  return getDateTimeStr(X509_get_notAfter(&x509));
160 }
static std::string getDateTimeStr(const ASN1_TIME *time)
std::string folly::ssl::OpenSSLCertUtils::getNotBeforeTime ( X509 &  x509)
static

Definition at line 162 of file OpenSSLCertUtils.cpp.

References getDateTimeStr().

Referenced by TEST_P().

162  {
163  return getDateTimeStr(X509_get_notBefore(&x509));
164 }
static std::string getDateTimeStr(const ASN1_TIME *time)
Optional< std::string > folly::ssl::OpenSSLCertUtils::getSubject ( X509 &  x509)
static

Definition at line 92 of file OpenSSLCertUtils.cpp.

References folly::none, and string.

Referenced by TEST_P().

92  {
93  auto subject = X509_get_subject_name(&x509);
94  if (!subject) {
95  return none;
96  }
97 
98  auto bio = BioUniquePtr(BIO_new(BIO_s_mem()));
99  if (bio == nullptr) {
100  throw std::runtime_error("Cannot allocate bio");
101  }
102  if (X509_NAME_print_ex(bio.get(), subject, 0, XN_FLAG_ONELINE) <= 0) {
103  return none;
104  }
105 
106  char* bioData = nullptr;
107  size_t bioLen = BIO_get_mem_data(bio.get(), &bioData);
108  return std::string(bioData, bioLen);
109 }
std::unique_ptr< BIO, BioDeleter > BioUniquePtr
const char * string
Definition: Conv.cpp:212
constexpr None none
Definition: Optional.h:87
std::vector< std::string > folly::ssl::OpenSSLCertUtils::getSubjectAltNames ( X509 &  x509)
static

Definition at line 64 of file OpenSSLCertUtils.cpp.

References folly::portability::ssl::ASN1_STRING_get0_data(), count, i, SCOPE_EXIT, and folly::portability::ssl::STACK_OF().

Referenced by fizz::SelfCertImpl< T >::getAltIdentities(), TEST_P(), and validateTestCertWithSAN().

64  {
65  auto names = reinterpret_cast<STACK_OF(GENERAL_NAME)*>(
66  X509_get_ext_d2i(&x509, NID_subject_alt_name, nullptr, nullptr));
67  if (!names) {
68  return {};
69  }
70  SCOPE_EXIT {
71  sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
72  };
73 
74  std::vector<std::string> ret;
75  auto count = sk_GENERAL_NAME_num(names);
76  for (int i = 0; i < count; i++) {
77  auto genName = sk_GENERAL_NAME_value(names, i);
78  if (!genName || genName->type != GEN_DNS) {
79  continue;
80  }
81  auto nameData = reinterpret_cast<const char*>(
82  ASN1_STRING_get0_data(genName->d.dNSName));
83  auto nameLen = ASN1_STRING_length(genName->d.dNSName);
84  if (!nameData || nameLen <= 0) {
85  continue;
86  }
87  ret.emplace_back(nameData, nameLen);
88  }
89  return ret;
90 }
STACK_OF(X509_OBJECT)*X509_STORE_get0_objects(X509_STORE *store)
Definition: OpenSSL.cpp:305
#define SCOPE_EXIT
Definition: ScopeGuard.h:274
unsigned char * ASN1_STRING_get0_data(const ASN1_STRING *x)
Definition: OpenSSL.cpp:199
int * count
std::vector< X509UniquePtr > folly::ssl::OpenSSLCertUtils::readCertsFromBuffer ( ByteRange  range)
static

Read certificates from memory and returns them as a vector of X509 pointers. Throw if there is any malformed cert or memory allocation problem.

Parameters
rangeBuffer to parse.
Returns
A vector of X509 objects.

Definition at line 209 of file OpenSSLCertUtils.cpp.

References b, folly::Range< Iter >::data(), folly::gen::move, and folly::Range< Iter >::size().

Referenced by fizz::server::test::FizzTestServer::enableClientAuthWithChain(), fizz::CertUtils::makePeerCert(), fizz::FizzUtil::readChainFile(), readStoreFromBuffer(), and TEST_P().

210  {
211  BioUniquePtr b(
212  BIO_new_mem_buf(const_cast<unsigned char*>(range.data()), range.size()));
213  if (!b) {
214  throw std::runtime_error("failed to create BIO");
215  }
216  std::vector<X509UniquePtr> certs;
217  ERR_clear_error();
218  while (true) {
219  X509UniquePtr x509(PEM_read_bio_X509(b.get(), nullptr, nullptr, nullptr));
220  if (x509) {
221  certs.push_back(std::move(x509));
222  continue;
223  }
224  auto err = ERR_get_error();
225  ERR_clear_error();
226  if (BIO_eof(b.get()) && ERR_GET_LIB(err) == ERR_LIB_PEM &&
227  ERR_GET_REASON(err) == PEM_R_NO_START_LINE) {
228  // Reach end of buffer.
229  break;
230  }
231  throw std::runtime_error(folly::to<std::string>(
232  "Unable to parse cert ",
233  certs.size(),
234  ": ",
235  getOpenSSLErrorString(err)));
236  }
237  return certs;
238 }
std::unique_ptr< X509, X509Deleter > X509UniquePtr
char b
std::unique_ptr< BIO, BioDeleter > BioUniquePtr
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
constexpr Range< Iter > range(Iter first, Iter last)
Definition: Range.h:1114
X509StoreUniquePtr folly::ssl::OpenSSLCertUtils::readStoreFromBuffer ( ByteRange  range)
static

Read a store from a PEM buffer. Throw if memory allocation fails, or any cert can't be parsed or added to the store.

Parameters
rangeA buffer containing certs in PEM format.
Returns
A X509 store that contains certs in the CA file.

Definition at line 273 of file OpenSSLCertUtils.cpp.

References readCertsFromBuffer().

Referenced by readStoreFromFile(), and TEST_P().

273  {
274  auto certs = readCertsFromBuffer(certRange);
275  ERR_clear_error();
276  folly::ssl::X509StoreUniquePtr store(X509_STORE_new());
277  for (auto& caCert : certs) {
278  if (X509_STORE_add_cert(store.get(), caCert.get()) != 1) {
279  auto err = ERR_get_error();
280  if (ERR_GET_LIB(err) != ERR_LIB_X509 ||
281  ERR_GET_REASON(err) != X509_R_CERT_ALREADY_IN_HASH_TABLE) {
282  throw std::runtime_error(folly::to<std::string>(
283  "Could not insert CA certificate into store: ",
284  getOpenSSLErrorString(err)));
285  }
286  }
287  }
288  return store;
289 }
std::unique_ptr< X509_STORE, X509StoreDeleter > X509StoreUniquePtr
static std::vector< X509UniquePtr > readCertsFromBuffer(ByteRange range)
X509StoreUniquePtr folly::ssl::OpenSSLCertUtils::readStoreFromFile ( std::string  caFile)
static

Read a store from a file. Throw if unable to read the file, memory allocation fails, or any cert can't be parsed or added to the store.

Parameters
caFilePath to the CA file.
Returns
A X509 store that contains certs in the CA file.

Definition at line 264 of file OpenSSLCertUtils.cpp.

References folly::readFile(), readStoreFromBuffer(), and string.

Referenced by fizz::JavaCryptoCertificateVerifier::createFromCAFile(), fizz::DefaultCertificateVerifier::createFromCAFile(), and TEST_P().

264  {
265  std::string certData;
266  if (!folly::readFile(caFile.c_str(), certData)) {
267  throw std::runtime_error(
268  folly::to<std::string>("Could not read store file: ", caFile));
269  }
270  return readStoreFromBuffer(folly::StringPiece(certData));
271 }
bool readFile(int fd, Container &out, size_t num_bytes=std::numeric_limits< size_t >::max())
Definition: FileUtil.h:125
static X509StoreUniquePtr readStoreFromBuffer(ByteRange range)
const char * string
Definition: Conv.cpp:212
folly::Optional< std::string > folly::ssl::OpenSSLCertUtils::toString ( X509 &  x509)
static

Definition at line 131 of file OpenSSLCertUtils.cpp.

References folly::none, and string.

Referenced by TEST_P().

131  {
132  auto in = BioUniquePtr(BIO_new(BIO_s_mem()));
133  if (in == nullptr) {
134  throw std::runtime_error("Cannot allocate bio");
135  }
136 
137  int flags = 0;
138 
139  flags |= X509_FLAG_NO_HEADER | /* A few bytes of cert and data */
140  X509_FLAG_NO_PUBKEY | /* Public key */
141  X509_FLAG_NO_AUX | /* Auxiliary info? */
142  X509_FLAG_NO_SIGDUMP | /* Prints the signature */
143  X509_FLAG_NO_SIGNAME; /* Signature algorithms */
144 
145 #ifdef X509_FLAG_NO_IDS
146  flags |= X509_FLAG_NO_IDS; /* Issuer/subject IDs */
147 #endif
148 
149  if (X509_print_ex(in.get(), &x509, XN_FLAG_ONELINE, flags) > 0) {
150  char* bioData = nullptr;
151  size_t bioLen = BIO_get_mem_data(in.get(), &bioData);
152  return std::string(bioData, bioLen);
153  } else {
154  return none;
155  }
156 }
flags
Definition: http_parser.h:127
std::unique_ptr< BIO, BioDeleter > BioUniquePtr
const char * string
Definition: Conv.cpp:212
constexpr None none
Definition: Optional.h:87

The documentation for this class was generated from the following files: