X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;ds=inline;f=folly%2Fio%2Fasync%2FSSLContext.h;h=bdd04509119d4c82b34d1d769716ea9b9a57e7b9;hb=3e19d28a142149241d81c5e736aa4117fe7cbec8;hp=e3ebaf5f7e8bc2486f8fbf90b3291d808e369403;hpb=03afacaf318c61b99ad09cd66ef028a38046fb48;p=folly.git diff --git a/folly/io/async/SSLContext.h b/folly/io/async/SSLContext.h index e3ebaf5f..bdd04509 100644 --- a/folly/io/async/SSLContext.h +++ b/folly/io/async/SSLContext.h @@ -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. @@ -16,19 +16,13 @@ #pragma once -#include #include #include -#include #include -#include +#include #include - -#include -#include - -#include -#include +#include +#include #include @@ -36,9 +30,13 @@ #include #endif +#include #include -#include +#include #include +#include +#include +#include namespace folly { @@ -58,7 +56,7 @@ class PasswordCollector { * @param password Pass collected password back to OpenSSL * @param size Maximum length of password including nullptr character */ - virtual void getPassword(std::string& password, int size) = 0; + virtual void getPassword(std::string& password, int size) const = 0; /** * Return a description of this collector for logging purposes @@ -71,11 +69,11 @@ class PasswordCollector { */ class SSLContext { public: - enum SSLVersion { - SSLv2, - SSLv3, - TLSv1 + SSLv2, + SSLv3, + TLSv1, // support TLS 1.0+ + TLSv1_2, // support for only TLS 1.2+ }; /** @@ -139,6 +137,78 @@ class SSLContext { */ virtual void setCiphersOrThrow(const std::string& ciphers); + /** + * Set default ciphers to be used in SSL handshake process. + */ + + template + void setCipherList(Iterator ibegin, Iterator iend) { + if (ibegin != iend) { + std::string opensslCipherList; + folly::join(":", ibegin, iend, opensslCipherList); + setCiphersOrThrow(opensslCipherList); + } + } + + template + void setCipherList(const Container& cipherList) { + using namespace std; + setCipherList(begin(cipherList), end(cipherList)); + } + + template + void setCipherList(const std::initializer_list& cipherList) { + setCipherList(cipherList.begin(), cipherList.end()); + } + + /** + * Sets the signature algorithms to be used during SSL negotiation + * for TLS1.2+. + */ + + template + void setSignatureAlgorithms(Iterator ibegin, Iterator iend) { + if (ibegin != iend) { +#if OPENSSL_VERSION_NUMBER >= 0x1000200fL + std::string opensslSigAlgsList; + join(":", ibegin, iend, opensslSigAlgsList); + if (!SSL_CTX_set1_sigalgs_list(ctx_, opensslSigAlgsList.c_str())) { + throw std::runtime_error("SSL_CTX_set1_sigalgs_list " + getErrors()); + } +#endif + } + } + + template + void setSignatureAlgorithms(const Container& sigalgs) { + using namespace std; + setSignatureAlgorithms(begin(sigalgs), end(sigalgs)); + } + + template + void setSignatureAlgorithms(const std::initializer_list& sigalgs) { + setSignatureAlgorithms(sigalgs.begin(), sigalgs.end()); + } + + /** + * Sets the list of EC curves supported by the client. + * + * @param ecCurves A list of ec curves, eg: P-256 + */ + void setClientECCurvesList(const std::vector& ecCurves); + + /** + * Method to add support for a specific elliptic curve encryption algorithm. + * + * @param curveName: The name of the ec curve to support, eg: prime256v1. + */ + void setServerECCurve(const std::string& curveName); + + /** + * Sets an x509 verification param on the context. + */ + void setX509VerifyParam(const ssl::X509VerifyParam& x509VerifyParam); + /** * Method to set verification option in the context object. * @@ -205,6 +275,7 @@ class SSLContext { * @param cert A PEM formatted certificate */ virtual void loadCertificateFromBufferPEM(folly::StringPiece cert); + /** * Load private key. * @@ -218,6 +289,41 @@ class SSLContext { * @param pkey A PEM formatted key */ virtual void loadPrivateKeyFromBufferPEM(folly::StringPiece pkey); + + /** + * Load cert and key from PEM buffers. Guaranteed to throw if cert and + * private key mismatch so no need to call isCertKeyPairValid. + * + * @param cert A PEM formatted certificate + * @param pkey A PEM formatted key + */ + virtual void loadCertKeyPairFromBufferPEM( + folly::StringPiece cert, + folly::StringPiece pkey); + + /** + * Load cert and key from files. Guaranteed to throw if cert and key mismatch. + * Equivalent to calling loadCertificate() and loadPrivateKey(). + * + * @param certPath Path to the certificate file + * @param keyPath Path to the private key file + * @param certFormat Certificate file format + * @param keyFormat Private key file format + */ + virtual void loadCertKeyPairFromFiles( + const char* certPath, + const char* keyPath, + const char* certFormat = "PEM", + const char* keyFormat = "PEM"); + + /** + * Call after both cert and key are loaded to check if cert matches key. + * Must call if private key is loaded before loading the cert. + * No need to call if cert is loaded first before private key. + * @return true if matches, or false if mismatch. + */ + virtual bool isCertKeyPairValid() const; + /** * Load trusted certificates from specified file. * @@ -248,7 +354,7 @@ class SSLContext { virtual std::shared_ptr passwordCollector() { return collector_; } -#if OPENSSL_VERSION_NUMBER >= 0x1000105fL && !defined(OPENSSL_NO_TLSEXT) +#if FOLLY_OPENSSL_HAS_SNI /** * Provide SNI support */ @@ -301,7 +407,7 @@ class SSLContext { */ typedef std::function ClientHelloCallback; virtual void addClientHelloCallback(const ClientHelloCallback& cb); -#endif +#endif // FOLLY_OPENSSL_HAS_SNI /** * Create an SSL object from this context. @@ -392,34 +498,6 @@ class SSLContext { return ctx_; } - enum SSLLockType { - LOCK_MUTEX, - LOCK_SPINLOCK, - LOCK_NONE - }; - - /** - * Set preferences for how to treat locks in OpenSSL. This must be - * called before the instantiation of any SSLContext objects, otherwise - * the defaults will be used. - * - * OpenSSL has a lock for each module rather than for each object or - * data that needs locking. Some locks protect only refcounts, and - * might be better as spinlocks rather than mutexes. Other locks - * may be totally unnecessary if the objects being protected are not - * shared between threads in the application. - * - * By default, all locks are initialized as mutexes. OpenSSL's lock usage - * may change from version to version and you should know what you are doing - * before disabling any locks entirely. - * - * Example: if you don't share SSL sessions between threads in your - * application, you may be able to do this - * - * setSSLLockTypes({{CRYPTO_LOCK_SSL_SESSION, SSLContext::LOCK_NONE}}) - */ - static void setSSLLockTypes(std::map lockTypes); - /** * Examine OpenSSL's error stack, and return a string description of the * errors. @@ -428,17 +506,6 @@ class SSLContext { */ static std::string getErrors(int errnoCopy); - /** - * We want to vary which cipher we'll use based on the client's TLS version. - * - * XXX: The refernces to tls11CipherString and tls11AltCipherlist are reused - * for * each >= TLS 1.1 handshake, so we expect these fields to not change. - */ - void switchCiphersIfTLS11( - SSL* ssl, - const std::string& tls11CipherString, - const std::vector>& tls11AltCipherlist); - bool checkPeerName() { return checkPeerName_; } std::string peerFixedName() { return peerFixedName_; } @@ -456,24 +523,8 @@ class SSLContext { */ static bool matchName(const char* host, const char* pattern, int size); - /** - * Functions for setting up and cleaning up openssl. - * They can be invoked during the start of the application. - */ + FOLLY_DEPRECATED("Use folly::ssl::init") static void initializeOpenSSL(); - static void cleanupOpenSSL(); - - /** - * Mark openssl as initialized without actually performing any initialization. - * Please use this only if you are using a library which requires that it must - * make its own calls to SSL_library_init() and related functions. - */ - static void markInitialized(); - - /** - * Default randomize method. - */ - static void randomize(); protected: SSL_CTX* ctx_; @@ -484,7 +535,7 @@ class SSLContext { bool checkPeerName_; std::string peerFixedName_; std::shared_ptr collector_; -#if OPENSSL_VERSION_NUMBER >= 0x1000105fL && !defined(OPENSSL_NO_TLSEXT) +#if FOLLY_OPENSSL_HAS_SNI ServerNameCallback serverNameCb_; std::vector clientHelloCbs_; #endif @@ -493,9 +544,6 @@ class SSLContext { static bool initialized_; - // To provide control over choice of server ciphersuites - std::unique_ptr> cipherListPicker_; - #ifdef OPENSSL_NPN_NEGOTIATED struct AdvertisedNextProtocolsItem { @@ -510,15 +558,13 @@ class SSLContext { std::vector advertisedNextProtocolWeights_; std::discrete_distribution nextProtocolDistribution_; - static int sNextProtocolsExDataIndex_; - static int advertisedNextProtocolCallback(SSL* ssl, const unsigned char** out, unsigned int* outlen, void* data); static int selectNextProtocolCallback( SSL* ssl, unsigned char **out, unsigned char *outlen, const unsigned char *server, unsigned int server_len, void *args); -#if OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined(OPENSSL_NO_TLSEXT) +#if FOLLY_OPENSSL_HAS_ALPN static int alpnSelectCallback(SSL* ssl, const unsigned char** out, unsigned char* outlen, @@ -532,7 +578,7 @@ class SSLContext { static int passwordCallback(char* password, int size, int, void* data); -#if OPENSSL_VERSION_NUMBER >= 0x1000105fL && !defined(OPENSSL_NO_TLSEXT) +#if FOLLY_OPENSSL_HAS_SNI /** * The function that will be called directly from openssl * in order for the application to get the tlsext_hostname just after @@ -551,15 +597,12 @@ class SSLContext { #endif std::string providedCiphersString_; - - // Functions are called when locked by the calling function. - static void initializeOpenSSLLocked(); - static void cleanupOpenSSLLocked(); }; typedef std::shared_ptr SSLContextPtr; -std::ostream& operator<<(std::ostream& os, const folly::PasswordCollector& collector); - +std::ostream& operator<<( + std::ostream& os, + const folly::PasswordCollector& collector); -} // folly +} // namespace folly