OpenSSL 1.1.0 compatibility
[folly.git] / folly / io / async / ssl / OpenSSLUtils.h
1 /*
2  * Copyright 2017 Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #pragma once
17
18 #include <folly/Range.h>
19 #include <folly/io/async/ssl/OpenSSLPtrTypes.h>
20 #include <folly/portability/Sockets.h>
21
22 #include <openssl/ssl.h>
23 #include <openssl/x509v3.h>
24
25 namespace folly {
26 namespace ssl {
27
28 class OpenSSLUtils {
29  public:
30   /*
31    * Get the TLS Session Master Key used to generate the TLS key material
32    *
33    * @param session ssl session
34    * @param keyOut destination for the master key, the buffer must be at least
35    * 48 bytes
36    * @return true if the master key is available (>= TLS1) and the output buffer
37    * large enough
38    */
39   static bool getTLSMasterKey(
40       const SSL_SESSION* session,
41       MutableByteRange keyOut);
42
43   /*
44    * Get the TLS Client Random used to generate the TLS key material
45    *
46    * @param ssl
47    * @param randomOut destination for the client random, the buffer must be at
48    * least 32 bytes
49    * @return true if the client random is available (>= TLS1) and the output
50    * buffer large enough
51    */
52   static bool getTLSClientRandom(const SSL* ssl, MutableByteRange randomOut);
53
54   /**
55    * Validate that the peer certificate's common name or subject alt names
56    * match what we expect.  Currently this only checks for IPs within
57    * subject alt names but it could easily be expanded to check common name
58    * and hostnames as well.
59    *
60    * @param cert    X509* peer certificate
61    * @param addr    sockaddr object containing sockaddr to verify
62    * @param addrLen length of sockaddr as returned by getpeername or accept
63    * @return true iff a subject altname IP matches addr
64    */
65   // TODO(agartrell): Add support for things like common name when
66   // necessary.
67   static bool validatePeerCertNames(X509* cert,
68                                     const sockaddr* addr,
69                                     socklen_t addrLen);
70
71   /**
72    * Get the peer socket address from an X509_STORE_CTX*.  Unlike the
73    * accept, getsockname, getpeername, etc family of operations, addrLen's
74    * initial value is ignored and reset.
75    *
76    * @param ctx         Context from which to retrieve peer sockaddr
77    * @param addrStorage out param for address
78    * @param addrLen     out param for length of address
79    * @return true on success, false on failure
80    */
81   static bool getPeerAddressFromX509StoreCtx(X509_STORE_CTX* ctx,
82                                              sockaddr_storage* addrStorage,
83                                              socklen_t* addrLen);
84
85   /**
86    * Get a stringified cipher name (e.g., ECDHE-ECDSA-CHACHA20-POLY1305) given
87    * the 2-byte code (e.g., 0xcca9) for the cipher. The name conversion only
88    * works for the ciphers built into the linked OpenSSL library
89    *
90    * @param cipherCode      A 16-bit IANA cipher code (machine endianness)
91    * @return Cipher name, or empty if the code is not found
92    */
93   static const std::string& getCipherName(uint16_t cipherCode);
94
95   /**
96    * Set the 'initial_ctx' SSL_CTX* inside an SSL. The initial_ctx is used to
97    * point to the SSL_CTX on which servername callback and session callbacks,
98    * as well as session caching stats are set. If we want to enforce SSL_CTX
99    * thread-based ownership (e.g., thread-local SSL_CTX) in the application, we
100    * need to also set/reset the initial_ctx when we call SSL_set_SSL_CTX.
101    *
102    * @param ssl      SSL pointer
103    * @param ctx      SSL_CTX pointer
104    * @return Cipher name, or empty if the code is not found
105    */
106   static void setSSLInitialCtx(SSL* ssl, SSL_CTX* ctx);
107   static SSL_CTX* getSSLInitialCtx(SSL* ssl);
108
109   /**
110   * Wrappers for BIO operations that may be different across different
111   * versions/flavors of OpenSSL (including forks like BoringSSL)
112   */
113   static BioMethodUniquePtr newSocketBioMethod();
114   static bool setCustomBioReadMethod(
115       BIO_METHOD* bioMeth,
116       int (*meth)(BIO*, char*, int));
117   static bool setCustomBioWriteMethod(
118       BIO_METHOD* bioMeth,
119       int (*meth)(BIO*, const char*, int));
120   static int getBioShouldRetryWrite(int ret);
121   static void setBioAppData(BIO* b, void* ptr);
122   static void* getBioAppData(BIO* b);
123   static int getBioFd(BIO* b, int* fd);
124   static void setBioFd(BIO* b, int fd, int flags);
125 };
126
127 } // ssl
128 } // folly