X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=folly%2Fportability%2FOpenSSL.cpp;h=845c441013a07f93b5525707d0ef38687a906313;hb=015306906e2811cc0cf3dab0c4142d45434a2801;hp=6c1f66dc7b7a7ffc57b3d6703b002f1b60762d3f;hpb=cff341f907bce289559edb3600ba13c65e336acf;p=folly.git diff --git a/folly/portability/OpenSSL.cpp b/folly/portability/OpenSSL.cpp index 6c1f66dc..845c4410 100644 --- a/folly/portability/OpenSSL.cpp +++ b/folly/portability/OpenSSL.cpp @@ -14,20 +14,106 @@ * limitations under the License. */ #include +#include + #include namespace folly { +namespace portability { namespace ssl { -#if FOLLY_OPENSSL_IS_110 -//////////////////////////////////////////////////////////////////////////////// -// APIs needed in 1.1.0 only -//////////////////////////////////////////////////////////////////////////////// +#if OPENSSL_IS_BORINGSSL +int SSL_CTX_set1_sigalgs_list(SSL_CTX*, const char*) { + return 1; // 0 implies error +} + +int TLS1_get_client_version(SSL* s) { + // Note that this isn't the client version, and the API to + // get this has been hidden. It may be found by parsing the + // ClientHello (there is a callback via the SSL_HANDSHAKE struct) + return s->version; +} +#endif + +#if FOLLY_OPENSSL_IS_100 +uint32_t SSL_CIPHER_get_id(const SSL_CIPHER* c) { + return c->id; +} + +int TLS1_get_client_version(const SSL* s) { + return (s->client_version >> 8) == TLS1_VERSION_MAJOR ? s->client_version : 0; +} +#endif + +#if FOLLY_OPENSSL_IS_100 || FOLLY_OPENSSL_IS_101 +int X509_get_signature_nid(X509* cert) { + return OBJ_obj2nid(cert->sig_alg->algorithm); +} +#endif + +#if FOLLY_OPENSSL_IS_100 || FOLLY_OPENSSL_IS_101 || FOLLY_OPENSSL_IS_102 +int SSL_CTX_up_ref(SSL_CTX* ctx) { + return CRYPTO_add(&ctx->references, 1, CRYPTO_LOCK_SSL_CTX); +} + +int SSL_SESSION_up_ref(SSL_SESSION* session) { + return CRYPTO_add(&session->references, 1, CRYPTO_LOCK_SSL_SESSION); +} + +int X509_up_ref(X509* x) { + return CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); +} + +int EVP_PKEY_up_ref(EVP_PKEY* evp) { + return CRYPTO_add(&evp->references, 1, CRYPTO_LOCK_EVP_PKEY); +} + +void RSA_get0_key( + const RSA* r, + const BIGNUM** n, + const BIGNUM** e, + const BIGNUM** d) { + if (n != nullptr) { + *n = r->n; + } + if (e != nullptr) { + *e = r->e; + } + if (d != nullptr) { + *d = r->d; + } +} -#else -//////////////////////////////////////////////////////////////////////////////// -// APIs needed in BoringSSL and OpenSSL < 1.1.0 (i.e., 1.0.2, 1.0.1, 1.0.0, etc) -//////////////////////////////////////////////////////////////////////////////// +RSA* EVP_PKEY_get0_RSA(EVP_PKEY* pkey) { + if (pkey->type != EVP_PKEY_RSA) { + return nullptr; + } + return pkey->pkey.rsa; +} + +DSA* EVP_PKEY_get0_DSA(EVP_PKEY* pkey) { + if (pkey->type != EVP_PKEY_DSA) { + return nullptr; + } + return pkey->pkey.dsa; +} + +DH* EVP_PKEY_get0_DH(EVP_PKEY* pkey) { + if (pkey->type != EVP_PKEY_DH) { + return nullptr; + } + return pkey->pkey.dh; +} + +EC_KEY* EVP_PKEY_get0_EC_KEY(EVP_PKEY* pkey) { + if (pkey->type != EVP_PKEY_EC) { + return nullptr; + } + return pkey->pkey.ec; +} +#endif + +#if !FOLLY_OPENSSL_IS_110 void BIO_meth_free(BIO_METHOD* biom) { OPENSSL_free((void*)biom); } @@ -42,36 +128,12 @@ int BIO_meth_set_write(BIO_METHOD* biom, int (*write)(BIO*, const char*, int)) { return 1; } -void EVP_MD_CTX_free(EVP_MD_CTX* ctx) { - EVP_MD_CTX_destroy(ctx); -} - const char* SSL_SESSION_get0_hostname(const SSL_SESSION* s) { return s->tlsext_hostname; } -EVP_MD_CTX* EVP_MD_CTX_new(void) { - EVP_MD_CTX* ctx = (EVP_MD_CTX*)OPENSSL_malloc(sizeof(EVP_MD_CTX)); - if (!ctx) { - throw std::runtime_error("Cannot allocate EVP_MD_CTX"); - } - EVP_MD_CTX_init(ctx); - return ctx; -} - -HMAC_CTX* HMAC_CTX_new(void) { - HMAC_CTX* ctx = (HMAC_CTX*)OPENSSL_malloc(sizeof(HMAC_CTX)); - if (!ctx) { - throw std::runtime_error("Cannot allocate HMAC_CTX"); - } - HMAC_CTX_init(ctx); - return ctx; -} - -void HMAC_CTX_free(HMAC_CTX* ctx) { - if (ctx) { - OPENSSL_free(ctx); - } +unsigned char* ASN1_STRING_get0_data(const ASN1_STRING* x) { + return ASN1_STRING_data((ASN1_STRING*)x); } int SSL_SESSION_has_ticket(const SSL_SESSION* s) { @@ -84,8 +146,8 @@ unsigned long SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION* s) { // This is taken from OpenSSL 1.1.0 int DH_set0_pqg(DH* dh, BIGNUM* p, BIGNUM* q, BIGNUM* g) { - /* If the fields p and g in d are NULL, the corresponding input - * parameters MUST be non-NULL. q may remain NULL. + /* If the fields p and g in d are nullptr, the corresponding input + * parameters MUST not be nullptr. q may remain nullptr. */ if (dh == nullptr || (dh->p == nullptr && p == nullptr) || (dh->g == nullptr && g == nullptr)) { @@ -116,66 +178,229 @@ int DH_set0_pqg(DH* dh, BIGNUM* p, BIGNUM* q, BIGNUM* g) { return 1; } -#ifdef OPENSSL_IS_BORINGSSL -//////////////////////////////////////////////////////////////////////////////// -// APIs needed in BoringSSL only -//////////////////////////////////////////////////////////////////////////////// -int SSL_CTX_set1_sigalgs_list(SSL_CTX*, const char*) { - return 1; // 0 implies error +void DH_get0_pqg( + const DH* dh, + const BIGNUM** p, + const BIGNUM** q, + const BIGNUM** g) { + // Based off of https://wiki.openssl.org/index.php/OpenSSL_1.1.0_Changes + if (p != nullptr) { + *p = dh->p; + } + if (q != nullptr) { + *q = dh->q; + } + if (g != nullptr) { + *g = dh->g; + } } -int TLS1_get_client_version(SSL* s) { - // Note that this isn't the client version, and the API to - // get this has been hidden. It may be found by parsing the - // ClientHello (there is a callback via the SSL_HANDSHAKE struct) - return s->version; +void DH_get0_key( + const DH* dh, + const BIGNUM** pub_key, + const BIGNUM** priv_key) { + // Based off of https://wiki.openssl.org/index.php/OpenSSL_1.1.0_Changes + if (pub_key != nullptr) { + *pub_key = dh->pub_key; + } + if (priv_key != nullptr) { + *priv_key = dh->priv_key; + } } -#elif FOLLY_OPENSSL_IS_102 || FOLLY_OPENSSL_IS_101 || FOLLY_OPENSSL_IS_100 -//////////////////////////////////////////////////////////////////////////////// -// APIs needed in 1.0.2 and 1.0.1/1.0.0 (both deprecated) -//////////////////////////////////////////////////////////////////////////////// -int SSL_CTX_up_ref(SSL_CTX* ctx) { - return CRYPTO_add(&ctx->references, 1, CRYPTO_LOCK_SSL_CTX); +void DSA_get0_pqg( + const DSA* dsa, + const BIGNUM** p, + const BIGNUM** q, + const BIGNUM** g) { + // Based off of https://wiki.openssl.org/index.php/OpenSSL_1.1.0_Changes + if (p != nullptr) { + *p = dsa->p; + } + if (q != nullptr) { + *q = dsa->q; + } + if (g != nullptr) { + *g = dsa->g; + } } -int SSL_SESSION_up_ref(SSL_SESSION* session) { - return CRYPTO_add(&session->references, 1, CRYPTO_LOCK_SSL_SESSION); +void DSA_get0_key( + const DSA* dsa, + const BIGNUM** pub_key, + const BIGNUM** priv_key) { + // Based off of https://wiki.openssl.org/index.php/OpenSSL_1.1.0_Changes + if (pub_key != nullptr) { + *pub_key = dsa->pub_key; + } + if (priv_key != nullptr) { + *priv_key = dsa->priv_key; + } } -int X509_up_ref(X509* x) { - return CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); +X509* X509_STORE_CTX_get0_cert(X509_STORE_CTX* ctx) { + return ctx->cert; } -#if FOLLY_OPENSSL_IS_101 || FOLLY_OPENSSL_IS_100 -//////////////////////////////////////////////////////////////////////////////// -// APIs needed in 1.0.1/1.0.0 (both deprecated) -//////////////////////////////////////////////////////////////////////////////// -int X509_get_signature_nid(X509* cert) { - return OBJ_obj2nid(cert->sig_alg->algorithm); +STACK_OF(X509) * X509_STORE_CTX_get0_chain(X509_STORE_CTX* ctx) { + return X509_STORE_CTX_get_chain(ctx); } -#endif +STACK_OF(X509) * X509_STORE_CTX_get0_untrusted(X509_STORE_CTX* ctx) { + return ctx->untrusted; +} -#if FOLLY_OPENSSL_IS_100 -//////////////////////////////////////////////////////////////////////////////// -// APIs needed only in 1.0.0 only (deprecated) -//////////////////////////////////////////////////////////////////////////////// -uint32_t SSL_CIPHER_get_id(const SSL_CIPHER* c) { - return c->id; +EVP_MD_CTX* EVP_MD_CTX_new() { + EVP_MD_CTX* ctx = (EVP_MD_CTX*)OPENSSL_malloc(sizeof(EVP_MD_CTX)); + if (!ctx) { + throw std::runtime_error("Cannot allocate EVP_MD_CTX"); + } + EVP_MD_CTX_init(ctx); + return ctx; } -int TLS1_get_client_version(const SSL* s) { - return (s->client_version >> 8) == TLS1_VERSION_MAJOR ? s->client_version : 0; +void EVP_MD_CTX_free(EVP_MD_CTX* ctx) { + if (ctx) { + EVP_MD_CTX_cleanup(ctx); + OPENSSL_free(ctx); + } } -#endif +HMAC_CTX* HMAC_CTX_new() { + HMAC_CTX* ctx = (HMAC_CTX*)OPENSSL_malloc(sizeof(HMAC_CTX)); + if (!ctx) { + throw std::runtime_error("Cannot allocate HMAC_CTX"); + } + HMAC_CTX_init(ctx); + return ctx; +} -#endif // !(OPENSSL_IS_BORINGSSL || -// FOLLY_OPENSSL_IS_101 || -// FOLLY_OPENSSL_IS_102 || -// FOLLY_OPENSSL_IS_100) +void HMAC_CTX_free(HMAC_CTX* ctx) { + if (ctx) { + HMAC_CTX_cleanup(ctx); + OPENSSL_free(ctx); + } +} -#endif // !FOLLY_OPENSSL_IS_110 +bool RSA_set0_key(RSA* r, BIGNUM* n, BIGNUM* e, BIGNUM* d) { + // Based off of https://wiki.openssl.org/index.php/OpenSSL_1.1.0_Changes + /** + * If the fields n and e in r are nullptr, the corresponding input parameters + * MUST be non-nullptr for n and e. d may be left NULL (in case only the + * public key is used). + */ + if ((r->n == nullptr && n == nullptr) || (r->e == nullptr && e == nullptr)) { + return false; + } + if (n != nullptr) { + BN_free(r->n); + r->n = n; + } + if (e != nullptr) { + BN_free(r->e); + r->e = e; + } + if (d != nullptr) { + BN_free(r->d); + r->d = d; + } + return true; } + +void RSA_get0_factors(const RSA* r, const BIGNUM** p, const BIGNUM** q) { + // Based off of https://wiki.openssl.org/index.php/OpenSSL_1.1.0_Changes + if (p != nullptr) { + *p = r->p; + } + if (q != nullptr) { + *q = r->q; + } } + +void RSA_get0_crt_params( + const RSA* r, + const BIGNUM** dmp1, + const BIGNUM** dmq1, + const BIGNUM** iqmp) { + // Based off of https://wiki.openssl.org/index.php/OpenSSL_1.1.0_Changes + if (dmp1 != nullptr) { + *dmp1 = r->dmp1; + } + if (dmq1 != nullptr) { + *dmq1 = r->dmq1; + } + if (iqmp != nullptr) { + *iqmp = r->iqmp; + } +} + +int ECDSA_SIG_set0(ECDSA_SIG* sig, BIGNUM* r, BIGNUM* s) { + // Based off of https://wiki.openssl.org/index.php/OpenSSL_1.1.0_Changes + if (r == nullptr || s == nullptr) { + return 0; + } + BN_clear_free(sig->r); + BN_clear_free(sig->s); + sig->r = r; + sig->s = s; + return 1; +} + +void ECDSA_SIG_get0( + const ECDSA_SIG* sig, + const BIGNUM** pr, + const BIGNUM** ps) { + // Based off of https://wiki.openssl.org/index.php/OpenSSL_1.1.0_Changes + if (pr != nullptr) { + *pr = sig->r; + } + if (ps != nullptr) { + *ps = sig->s; + } +} + +/** + * Compatibility shim for OpenSSL < 1.1.0. + * + * For now, options and settings are ignored. We implement the most common + * behavior, which is to add all digests, ciphers, and strings. + */ +int OPENSSL_init_ssl(uint64_t, const OPENSSL_INIT_SETTINGS*) { + // OpenSSL >= 1.1.0 handles initializing the library, adding digests & + // ciphers, loading strings. Additionally, OpenSSL >= 1.1.0 uses platform + // native threading & mutexes, which means that we should handle setting up + // the necessary threading initialization in the compat layer as well. + SSL_library_init(); + OpenSSL_add_all_ciphers(); + OpenSSL_add_all_digests(); + OpenSSL_add_all_algorithms(); + + SSL_load_error_strings(); + ERR_load_crypto_strings(); + + // The caller should have used SSLContext::setLockTypes() prior to calling + // this function. + folly::ssl::detail::installThreadingLocks(); + return 0; +} + +void OPENSSL_cleanup() { + folly::ssl::detail::cleanupThreadingLocks(); + CRYPTO_cleanup_all_ex_data(); + ERR_free_strings(); + EVP_cleanup(); + ERR_clear_error(); +} + +const ASN1_INTEGER* X509_REVOKED_get0_serialNumber(const X509_REVOKED* r) { + return r->serialNumber; +} + +const ASN1_TIME* X509_REVOKED_get0_revocationDate(const X509_REVOKED* r) { + return r->revocationDate; +} + +#endif // !FOLLY_OPENSSL_IS_110 +} // namespace ssl +} // namespace portability +} // namespace folly