2 * Copyright 2017 Facebook, Inc.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include <folly/Range.h>
19 #include <folly/io/async/ssl/OpenSSLPtrTypes.h>
20 #include <folly/portability/Sockets.h>
22 #include <openssl/ssl.h>
23 #include <openssl/x509v3.h>
31 * Get the TLS Session Master Key used to generate the TLS key material
33 * @param session ssl session
34 * @param keyOut destination for the master key, the buffer must be at least
36 * @return true if the master key is available (>= TLS1) and the output buffer
39 static bool getTLSMasterKey(
40 const SSL_SESSION* session,
41 MutableByteRange keyOut);
44 * Get the TLS Client Random used to generate the TLS key material
47 * @param randomOut destination for the client random, the buffer must be at
49 * @return true if the client random is available (>= TLS1) and the output
52 static bool getTLSClientRandom(const SSL* ssl, MutableByteRange randomOut);
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.
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
65 // TODO(agartrell): Add support for things like common name when
67 static bool validatePeerCertNames(X509* cert,
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.
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
81 static bool getPeerAddressFromX509StoreCtx(X509_STORE_CTX* ctx,
82 sockaddr_storage* addrStorage,
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
90 * @param cipherCode A 16-bit IANA cipher code (machine endianness)
91 * @return Cipher name, or empty if the code is not found
93 static const std::string& getCipherName(uint16_t cipherCode);
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.
102 * @param ssl SSL pointer
103 * @param ctx SSL_CTX pointer
104 * @return Cipher name, or empty if the code is not found
106 static void setSSLInitialCtx(SSL* ssl, SSL_CTX* ctx);
107 static SSL_CTX* getSSLInitialCtx(SSL* ssl);
110 * Wrappers for BIO operations that may be different across different
111 * versions/flavors of OpenSSL (including forks like BoringSSL)
113 static BioMethodUniquePtr newSocketBioMethod();
114 static bool setCustomBioReadMethod(
116 int (*meth)(BIO*, char*, int));
117 static bool setCustomBioWriteMethod(
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);