Add wrapper for getting X509_digest from a cert
[folly.git] / folly / ssl / OpenSSLCertUtils.cpp
index 9dbbe46a4bc4e3003750a82ec956d8665fb90095..ac7cd7414f2159e68be9ce587e0624080cd9aa2e 100644 (file)
@@ -17,7 +17,7 @@
 
 #include <folly/ScopeGuard.h>
 #include <folly/String.h>
-#include <folly/io/async/ssl/OpenSSLPtrTypes.h>
+#include <folly/ssl/OpenSSLPtrTypes.h>
 
 namespace folly {
 namespace ssl {
@@ -159,8 +159,6 @@ std::string OpenSSLCertUtils::getDateTimeStr(const ASN1_TIME* time) {
     return "";
   }
 
-  std::array<char, 32> buf;
-
   auto bio = BioUniquePtr(BIO_new(BIO_s_mem()));
   if (bio == nullptr) {
     throw std::runtime_error("Cannot allocate bio");
@@ -175,5 +173,73 @@ std::string OpenSSLCertUtils::getDateTimeStr(const ASN1_TIME* time) {
   return std::string(bioData, bioLen);
 }
 
-} // ssl
-} // folly
+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;
+}
+
+std::vector<X509UniquePtr> OpenSSLCertUtils::readCertsFromBuffer(
+    ByteRange range) {
+  BioUniquePtr b(
+      BIO_new_mem_buf(const_cast<unsigned char*>(range.data()), range.size()));
+  if (!b) {
+    throw std::runtime_error("failed to create BIO");
+  }
+  std::vector<X509UniquePtr> certs;
+  while (true) {
+    X509UniquePtr x509(PEM_read_bio_X509(b.get(), nullptr, nullptr, nullptr));
+    if (!x509) {
+      break;
+    }
+    certs.push_back(std::move(x509));
+  }
+
+  return certs;
+}
+
+std::array<uint8_t, SHA_DIGEST_LENGTH> OpenSSLCertUtils::getDigestSha1(
+    X509& x509) {
+  unsigned int len;
+  std::array<uint8_t, SHA_DIGEST_LENGTH> md;
+  int rc = X509_digest(&x509, EVP_sha1(), md.data(), &len);
+
+  if (rc <= 0) {
+    throw std::runtime_error("Could not calculate SHA1 digest for cert");
+  }
+  return md;
+}
+
+std::array<uint8_t, SHA256_DIGEST_LENGTH> OpenSSLCertUtils::getDigestSha256(
+    X509& x509) {
+  unsigned int len;
+  std::array<uint8_t, SHA256_DIGEST_LENGTH> md;
+  int rc = X509_digest(&x509, EVP_sha256(), md.data(), &len);
+
+  if (rc <= 0) {
+    throw std::runtime_error("Could not calculate SHA256 digest for cert");
+  }
+  return md;
+}
+
+
+} // namespace ssl
+} // namespace folly