OpenSSL 1.1.0 compatibility
[folly.git] / folly / io / async / ssl / OpenSSLUtils.h
index 7f211bfd1e76c43a79db6ce1db25cdaf6bd65c1f..877df15667433ea8f72ebe7ccb8f93873986bd92 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016 Facebook, Inc.
+ * Copyright 2017 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  */
 #pragma once
 
+#include <folly/Range.h>
+#include <folly/io/async/ssl/OpenSSLPtrTypes.h>
 #include <folly/portability/Sockets.h>
 
+#include <openssl/ssl.h>
 #include <openssl/x509v3.h>
 
 namespace folly {
@@ -24,6 +27,30 @@ namespace ssl {
 
 class OpenSSLUtils {
  public:
+  /*
+   * Get the TLS Session Master Key used to generate the TLS key material
+   *
+   * @param session ssl session
+   * @param keyOut destination for the master key, the buffer must be at least
+   * 48 bytes
+   * @return true if the master key is available (>= TLS1) and the output buffer
+   * large enough
+   */
+  static bool getTLSMasterKey(
+      const SSL_SESSION* session,
+      MutableByteRange keyOut);
+
+  /*
+   * Get the TLS Client Random used to generate the TLS key material
+   *
+   * @param ssl
+   * @param randomOut destination for the client random, the buffer must be at
+   * least 32 bytes
+   * @return true if the client random is available (>= TLS1) and the output
+   * buffer large enough
+   */
+  static bool getTLSClientRandom(const SSL* ssl, MutableByteRange randomOut);
+
   /**
    * Validate that the peer certificate's common name or subject alt names
    * match what we expect.  Currently this only checks for IPs within
@@ -54,6 +81,47 @@ class OpenSSLUtils {
   static bool getPeerAddressFromX509StoreCtx(X509_STORE_CTX* ctx,
                                              sockaddr_storage* addrStorage,
                                              socklen_t* addrLen);
+
+  /**
+   * Get a stringified cipher name (e.g., ECDHE-ECDSA-CHACHA20-POLY1305) given
+   * the 2-byte code (e.g., 0xcca9) for the cipher. The name conversion only
+   * works for the ciphers built into the linked OpenSSL library
+   *
+   * @param cipherCode      A 16-bit IANA cipher code (machine endianness)
+   * @return Cipher name, or empty if the code is not found
+   */
+  static const std::string& getCipherName(uint16_t cipherCode);
+
+  /**
+   * Set the 'initial_ctx' SSL_CTX* inside an SSL. The initial_ctx is used to
+   * point to the SSL_CTX on which servername callback and session callbacks,
+   * as well as session caching stats are set. If we want to enforce SSL_CTX
+   * thread-based ownership (e.g., thread-local SSL_CTX) in the application, we
+   * need to also set/reset the initial_ctx when we call SSL_set_SSL_CTX.
+   *
+   * @param ssl      SSL pointer
+   * @param ctx      SSL_CTX pointer
+   * @return Cipher name, or empty if the code is not found
+   */
+  static void setSSLInitialCtx(SSL* ssl, SSL_CTX* ctx);
+  static SSL_CTX* getSSLInitialCtx(SSL* ssl);
+
+  /**
+  * Wrappers for BIO operations that may be different across different
+  * versions/flavors of OpenSSL (including forks like BoringSSL)
+  */
+  static BioMethodUniquePtr newSocketBioMethod();
+  static bool setCustomBioReadMethod(
+      BIO_METHOD* bioMeth,
+      int (*meth)(BIO*, char*, int));
+  static bool setCustomBioWriteMethod(
+      BIO_METHOD* bioMeth,
+      int (*meth)(BIO*, const char*, int));
+  static int getBioShouldRetryWrite(int ret);
+  static void setBioAppData(BIO* b, void* ptr);
+  static void* getBioAppData(BIO* b);
+  static int getBioFd(BIO* b, int* fd);
+  static void setBioFd(BIO* b, int fd, int flags);
 };
 
 } // ssl