1 /*
2  * Copyright (c) Facebook, Inc. and its affiliates.
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 
17 #include <folly/portability/OpenSSL.h>
18 #include <folly/ssl/detail/OpenSSLThreading.h>
19 
20 #include <stdexcept>
21 
22 namespace folly {
23 namespace portability {
24 namespace ssl {
25 
26 #ifdef OPENSSL_IS_BORINGSSL
SSL_CTX_set1_sigalgs_list(SSL_CTX *,const char *)27 int SSL_CTX_set1_sigalgs_list(SSL_CTX*, const char*) {
28   return 1; // 0 implies error
29 }
30 
TLS1_get_client_version(SSL * s)31 int TLS1_get_client_version(SSL* s) {
32   // Note that this isn't the client version, and the API to
33   // get this has been hidden. It may be found by parsing the
34   // ClientHello (there is a callback via the SSL_HANDSHAKE struct)
35   return s->version;
36 }
37 #endif
38 
39 #if FOLLY_OPENSSL_IS_100
SSL_CIPHER_get_id(const SSL_CIPHER * c)40 uint32_t SSL_CIPHER_get_id(const SSL_CIPHER* c) {
41   return c->id;
42 }
43 
TLS1_get_client_version(const SSL * s)44 int TLS1_get_client_version(const SSL* s) {
45   return (s->client_version >> 8) == TLS1_VERSION_MAJOR ? s->client_version : 0;
46 }
47 #endif
48 
49 #if FOLLY_OPENSSL_IS_100 || FOLLY_OPENSSL_IS_101
X509_get_signature_nid(X509 * cert)50 int X509_get_signature_nid(X509* cert) {
51   return OBJ_obj2nid(cert->sig_alg->algorithm);
52 }
53 #endif
54 
55 #if FOLLY_OPENSSL_IS_100 || FOLLY_OPENSSL_IS_101 || FOLLY_OPENSSL_IS_102
SSL_CTX_up_ref(SSL_CTX * ctx)56 int SSL_CTX_up_ref(SSL_CTX* ctx) {
57   return CRYPTO_add(&ctx->references, 1, CRYPTO_LOCK_SSL_CTX);
58 }
59 
SSL_SESSION_up_ref(SSL_SESSION * session)60 int SSL_SESSION_up_ref(SSL_SESSION* session) {
61   return CRYPTO_add(&session->references, 1, CRYPTO_LOCK_SSL_SESSION);
62 }
63 
X509_up_ref(X509 * x)64 int X509_up_ref(X509* x) {
65   return CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509);
66 }
67 
X509_STORE_CTX_set0_verified_chain(X509_STORE_CTX * ctx,STACK_OF (X509)* sk)68 void X509_STORE_CTX_set0_verified_chain(
69     X509_STORE_CTX* ctx, STACK_OF(X509) * sk) {
70   sk_X509_pop_free(ctx->chain, X509_free);
71   ctx->chain = sk;
72 }
73 
X509_STORE_up_ref(X509_STORE * v)74 int X509_STORE_up_ref(X509_STORE* v) {
75   return CRYPTO_add(&v->references, 1, CRYPTO_LOCK_X509_STORE);
76 }
77 
EVP_PKEY_up_ref(EVP_PKEY * evp)78 int EVP_PKEY_up_ref(EVP_PKEY* evp) {
79   return CRYPTO_add(&evp->references, 1, CRYPTO_LOCK_EVP_PKEY);
80 }
81 
RSA_get0_key(const RSA * r,const BIGNUM ** n,const BIGNUM ** e,const BIGNUM ** d)82 void RSA_get0_key(
83     const RSA* r, const BIGNUM** n, const BIGNUM** e, const BIGNUM** d) {
84   if (n != nullptr) {
85     *n = r->n;
86   }
87   if (e != nullptr) {
88     *e = r->e;
89   }
90   if (d != nullptr) {
91     *d = r->d;
92   }
93 }
94 
EVP_PKEY_get0_RSA(EVP_PKEY * pkey)95 RSA* EVP_PKEY_get0_RSA(EVP_PKEY* pkey) {
96   if (pkey->type != EVP_PKEY_RSA) {
97     return nullptr;
98   }
99   return pkey->pkey.rsa;
100 }
101 
EVP_PKEY_get0_DSA(EVP_PKEY * pkey)102 DSA* EVP_PKEY_get0_DSA(EVP_PKEY* pkey) {
103   if (pkey->type != EVP_PKEY_DSA) {
104     return nullptr;
105   }
106   return pkey->pkey.dsa;
107 }
108 
EVP_PKEY_get0_DH(EVP_PKEY * pkey)109 DH* EVP_PKEY_get0_DH(EVP_PKEY* pkey) {
110   if (pkey->type != EVP_PKEY_DH) {
111     return nullptr;
112   }
113   return pkey->pkey.dh;
114 }
115 
EVP_PKEY_get0_EC_KEY(EVP_PKEY * pkey)116 EC_KEY* EVP_PKEY_get0_EC_KEY(EVP_PKEY* pkey) {
117   if (pkey->type != EVP_PKEY_EC) {
118     return nullptr;
119   }
120   return pkey->pkey.ec;
121 }
122 #endif
123 
124 #if !FOLLY_OPENSSL_IS_110
BIO_meth_new(int type,const char * name)125 BIO_METHOD* BIO_meth_new(int type, const char* name) {
126   BIO_METHOD* method = (BIO_METHOD*)OPENSSL_malloc(sizeof(BIO_METHOD));
127   if (method == nullptr) {
128     return nullptr;
129   }
130   memset(method, 0, sizeof(BIO_METHOD));
131   method->type = type;
132   method->name = name;
133   return method;
134 }
135 
BIO_meth_free(BIO_METHOD * biom)136 void BIO_meth_free(BIO_METHOD* biom) {
137   OPENSSL_free((void*)biom);
138 }
139 
BIO_meth_set_read(BIO_METHOD * biom,int (* read)(BIO *,char *,int))140 int BIO_meth_set_read(BIO_METHOD* biom, int (*read)(BIO*, char*, int)) {
141   biom->bread = read;
142   return 1;
143 }
144 
BIO_meth_set_write(BIO_METHOD * biom,int (* write)(BIO *,const char *,int))145 int BIO_meth_set_write(BIO_METHOD* biom, int (*write)(BIO*, const char*, int)) {
146   biom->bwrite = write;
147   return 1;
148 }
149 
BIO_meth_set_puts(BIO_METHOD * biom,int (* bputs)(BIO *,const char *))150 int BIO_meth_set_puts(BIO_METHOD* biom, int (*bputs)(BIO*, const char*)) {
151   biom->bputs = bputs;
152   return 1;
153 }
154 
BIO_meth_set_gets(BIO_METHOD * biom,int (* bgets)(BIO *,char *,int))155 int BIO_meth_set_gets(BIO_METHOD* biom, int (*bgets)(BIO*, char*, int)) {
156   biom->bgets = bgets;
157   return 1;
158 }
159 
BIO_meth_set_ctrl(BIO_METHOD * biom,long (* ctrl)(BIO *,int,long,void *))160 int BIO_meth_set_ctrl(BIO_METHOD* biom, long (*ctrl)(BIO*, int, long, void*)) {
161   biom->ctrl = ctrl;
162   return 1;
163 }
164 
BIO_meth_set_create(BIO_METHOD * biom,int (* create)(BIO *))165 int BIO_meth_set_create(BIO_METHOD* biom, int (*create)(BIO*)) {
166   biom->create = create;
167   return 1;
168 }
169 
BIO_meth_set_destroy(BIO_METHOD * biom,int (* destroy)(BIO *))170 int BIO_meth_set_destroy(BIO_METHOD* biom, int (*destroy)(BIO*)) {
171   biom->destroy = destroy;
172   return 1;
173 }
174 
BIO_set_data(BIO * bio,void * ptr)175 void BIO_set_data(BIO* bio, void* ptr) {
176   bio->ptr = ptr;
177 }
178 
BIO_get_data(BIO * bio)179 void* BIO_get_data(BIO* bio) {
180   return bio->ptr;
181 }
182 
BIO_set_init(BIO * bio,int init)183 void BIO_set_init(BIO* bio, int init) {
184   bio->init = init;
185 }
186 
BIO_set_shutdown(BIO * bio,int shutdown)187 void BIO_set_shutdown(BIO* bio, int shutdown) {
188   bio->shutdown = shutdown;
189 }
190 
TLS_server_method(void)191 const SSL_METHOD* TLS_server_method(void) {
192   return TLSv1_2_server_method();
193 }
194 
TLS_client_method(void)195 const SSL_METHOD* TLS_client_method(void) {
196   return TLSv1_2_client_method();
197 }
198 
SSL_SESSION_get0_hostname(const SSL_SESSION * s)199 const char* SSL_SESSION_get0_hostname(const SSL_SESSION* s) {
200   return s->tlsext_hostname;
201 }
202 
ASN1_STRING_get0_data(const ASN1_STRING * x)203 unsigned char* ASN1_STRING_get0_data(const ASN1_STRING* x) {
204   return ASN1_STRING_data((ASN1_STRING*)x);
205 }
206 
SSL_SESSION_has_ticket(const SSL_SESSION * s)207 int SSL_SESSION_has_ticket(const SSL_SESSION* s) {
208   return (s->tlsext_ticklen > 0) ? 1 : 0;
209 }
210 
SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION * s)211 unsigned long SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION* s) {
212   return s->tlsext_tick_lifetime_hint;
213 }
214 
215 // This is taken from OpenSSL 1.1.0
DH_set0_pqg(DH * dh,BIGNUM * p,BIGNUM * q,BIGNUM * g)216 int DH_set0_pqg(DH* dh, BIGNUM* p, BIGNUM* q, BIGNUM* g) {
217   /* If the fields p and g in d are nullptr, the corresponding input
218    * parameters MUST not be nullptr.  q may remain nullptr.
219    */
220   if (dh == nullptr || (dh->p == nullptr && p == nullptr) ||
221       (dh->g == nullptr && g == nullptr)) {
222     return 0;
223   }
224 
225   if (p != nullptr) {
226     BN_free(dh->p);
227     dh->p = p;
228   }
229   if (q != nullptr) {
230     BN_free(dh->q);
231     dh->q = q;
232   }
233   if (g != nullptr) {
234     BN_free(dh->g);
235     dh->g = g;
236   }
237 
238   // In OpenSSL 1.1.0, DH_set0_pqg also sets
239   //   dh->length = BN_num_bits(q)
240   // With OpenSSL 1.0.2, the output of openssl dhparam -C 2048 doesn't set
241   // the length field. So as far as the compat lib is concerned, this wrapper
242   // mimics the functionality of OpenSSL 1.0.2
243   // Note: BoringSSL doesn't even have a length field anymore, just something
244   // called 'priv_length'. Let's not mess with that for now.
245 
246   return 1;
247 }
248 
DH_get0_pqg(const DH * dh,const BIGNUM ** p,const BIGNUM ** q,const BIGNUM ** g)249 void DH_get0_pqg(
250     const DH* dh, const BIGNUM** p, const BIGNUM** q, const BIGNUM** g) {
251   // Based off of https://wiki.openssl.org/index.php/OpenSSL_1.1.0_Changes
252   if (p != nullptr) {
253     *p = dh->p;
254   }
255   if (q != nullptr) {
256     *q = dh->q;
257   }
258   if (g != nullptr) {
259     *g = dh->g;
260   }
261 }
262 
DH_get0_key(const DH * dh,const BIGNUM ** pub_key,const BIGNUM ** priv_key)263 void DH_get0_key(
264     const DH* dh, const BIGNUM** pub_key, const BIGNUM** priv_key) {
265   // Based off of https://wiki.openssl.org/index.php/OpenSSL_1.1.0_Changes
266   if (pub_key != nullptr) {
267     *pub_key = dh->pub_key;
268   }
269   if (priv_key != nullptr) {
270     *priv_key = dh->priv_key;
271   }
272 }
273 
DH_get_length(const DH * dh)274 long DH_get_length(const DH* dh) {
275   return dh->length;
276 }
277 
DH_set_length(DH * dh,long length)278 int DH_set_length(DH* dh, long length) {
279   if (dh != nullptr) {
280     dh->length = length;
281     return 1;
282   } else {
283     return 0;
284   }
285 }
286 
DSA_get0_pqg(const DSA * dsa,const BIGNUM ** p,const BIGNUM ** q,const BIGNUM ** g)287 void DSA_get0_pqg(
288     const DSA* dsa, const BIGNUM** p, const BIGNUM** q, const BIGNUM** g) {
289   // Based off of https://wiki.openssl.org/index.php/OpenSSL_1.1.0_Changes
290   if (p != nullptr) {
291     *p = dsa->p;
292   }
293   if (q != nullptr) {
294     *q = dsa->q;
295   }
296   if (g != nullptr) {
297     *g = dsa->g;
298   }
299 }
300 
DSA_get0_key(const DSA * dsa,const BIGNUM ** pub_key,const BIGNUM ** priv_key)301 void DSA_get0_key(
302     const DSA* dsa, const BIGNUM** pub_key, const BIGNUM** priv_key) {
303   // Based off of https://wiki.openssl.org/index.php/OpenSSL_1.1.0_Changes
304   if (pub_key != nullptr) {
305     *pub_key = dsa->pub_key;
306   }
307   if (priv_key != nullptr) {
308     *priv_key = dsa->priv_key;
309   }
310 }
311 
STACK_OF(X509_OBJECT)312 STACK_OF(X509_OBJECT) * X509_STORE_get0_objects(X509_STORE* store) {
313   return store->objs;
314 }
315 
X509_STORE_CTX_get0_cert(X509_STORE_CTX * ctx)316 X509* X509_STORE_CTX_get0_cert(X509_STORE_CTX* ctx) {
317   return ctx->cert;
318 }
319 
STACK_OF(X509)320 STACK_OF(X509) * X509_STORE_CTX_get0_chain(X509_STORE_CTX* ctx) {
321   return X509_STORE_CTX_get_chain(ctx);
322 }
323 
STACK_OF(X509)324 STACK_OF(X509) * X509_STORE_CTX_get0_untrusted(X509_STORE_CTX* ctx) {
325   return ctx->untrusted;
326 }
327 
EVP_MD_CTX_new()328 EVP_MD_CTX* EVP_MD_CTX_new() {
329   EVP_MD_CTX* ctx = (EVP_MD_CTX*)OPENSSL_malloc(sizeof(EVP_MD_CTX));
330   if (!ctx) {
331     throw std::runtime_error("Cannot allocate EVP_MD_CTX");
332   }
333   EVP_MD_CTX_init(ctx);
334   return ctx;
335 }
336 
EVP_MD_CTX_free(EVP_MD_CTX * ctx)337 void EVP_MD_CTX_free(EVP_MD_CTX* ctx) {
338   if (ctx) {
339     EVP_MD_CTX_cleanup(ctx);
340     OPENSSL_free(ctx);
341   }
342 }
343 
HMAC_CTX_new()344 HMAC_CTX* HMAC_CTX_new() {
345   HMAC_CTX* ctx = (HMAC_CTX*)OPENSSL_malloc(sizeof(HMAC_CTX));
346   if (!ctx) {
347     throw std::runtime_error("Cannot allocate HMAC_CTX");
348   }
349   HMAC_CTX_init(ctx);
350   return ctx;
351 }
352 
HMAC_CTX_free(HMAC_CTX * ctx)353 void HMAC_CTX_free(HMAC_CTX* ctx) {
354   if (ctx) {
355     HMAC_CTX_cleanup(ctx);
356     OPENSSL_free(ctx);
357   }
358 }
359 
RSA_set0_key(RSA * r,BIGNUM * n,BIGNUM * e,BIGNUM * d)360 bool RSA_set0_key(RSA* r, BIGNUM* n, BIGNUM* e, BIGNUM* d) {
361   // Based off of https://wiki.openssl.org/index.php/OpenSSL_1.1.0_Changes
362   /**
363    * If the fields n and e in r are nullptr, the corresponding input parameters
364    * MUST be non-nullptr for n and e. d may be left NULL (in case only the
365    * public key is used).
366    */
367   if ((r->n == nullptr && n == nullptr) || (r->e == nullptr && e == nullptr)) {
368     return false;
369   }
370   if (n != nullptr) {
371     BN_free(r->n);
372     r->n = n;
373   }
374   if (e != nullptr) {
375     BN_free(r->e);
376     r->e = e;
377   }
378   if (d != nullptr) {
379     BN_free(r->d);
380     r->d = d;
381   }
382   return true;
383 }
384 
RSA_get0_factors(const RSA * r,const BIGNUM ** p,const BIGNUM ** q)385 void RSA_get0_factors(const RSA* r, const BIGNUM** p, const BIGNUM** q) {
386   // Based off of https://wiki.openssl.org/index.php/OpenSSL_1.1.0_Changes
387   if (p != nullptr) {
388     *p = r->p;
389   }
390   if (q != nullptr) {
391     *q = r->q;
392   }
393 }
394 
RSA_get0_crt_params(const RSA * r,const BIGNUM ** dmp1,const BIGNUM ** dmq1,const BIGNUM ** iqmp)395 void RSA_get0_crt_params(
396     const RSA* r,
397     const BIGNUM** dmp1,
398     const BIGNUM** dmq1,
399     const BIGNUM** iqmp) {
400   // Based off of https://wiki.openssl.org/index.php/OpenSSL_1.1.0_Changes
401   if (dmp1 != nullptr) {
402     *dmp1 = r->dmp1;
403   }
404   if (dmq1 != nullptr) {
405     *dmq1 = r->dmq1;
406   }
407   if (iqmp != nullptr) {
408     *iqmp = r->iqmp;
409   }
410 }
411 
ECDSA_SIG_set0(ECDSA_SIG * sig,BIGNUM * r,BIGNUM * s)412 int ECDSA_SIG_set0(ECDSA_SIG* sig, BIGNUM* r, BIGNUM* s) {
413   // Based off of https://wiki.openssl.org/index.php/OpenSSL_1.1.0_Changes
414   if (r == nullptr || s == nullptr) {
415     return 0;
416   }
417   BN_clear_free(sig->r);
418   BN_clear_free(sig->s);
419   sig->r = r;
420   sig->s = s;
421   return 1;
422 }
423 
ECDSA_SIG_get0(const ECDSA_SIG * sig,const BIGNUM ** pr,const BIGNUM ** ps)424 void ECDSA_SIG_get0(
425     const ECDSA_SIG* sig, const BIGNUM** pr, const BIGNUM** ps) {
426   // Based off of https://wiki.openssl.org/index.php/OpenSSL_1.1.0_Changes
427   if (pr != nullptr) {
428     *pr = sig->r;
429   }
430   if (ps != nullptr) {
431     *ps = sig->s;
432   }
433 }
434 
435 /**
436  * Compatibility shim for OpenSSL < 1.1.0.
437  *
438  * For now, options and settings are ignored. We implement the most common
439  * behavior, which is to add all digests, ciphers, and strings.
440  */
OPENSSL_init_ssl(uint64_t,const OPENSSL_INIT_SETTINGS *)441 int OPENSSL_init_ssl(uint64_t, const OPENSSL_INIT_SETTINGS*) {
442   // OpenSSL >= 1.1.0 handles initializing the library, adding digests &
443   // ciphers, loading strings. Additionally, OpenSSL >= 1.1.0 uses platform
444   // native threading & mutexes, which means that we should handle setting up
445   // the necessary threading initialization in the compat layer as well.
446   SSL_library_init();
447   OpenSSL_add_all_ciphers();
448   OpenSSL_add_all_digests();
449   OpenSSL_add_all_algorithms();
450 
451   SSL_load_error_strings();
452   ERR_load_crypto_strings();
453 
454   // The caller should have used SSLContext::setLockTypes() prior to calling
455   // this function.
456   folly::ssl::detail::installThreadingLocks();
457   return 1;
458 }
459 
OPENSSL_cleanup()460 void OPENSSL_cleanup() {
461   folly::ssl::detail::cleanupThreadingLocks();
462   CRYPTO_cleanup_all_ex_data();
463   ERR_free_strings();
464   EVP_cleanup();
465   ERR_clear_error();
466 }
467 
X509_REVOKED_get0_serialNumber(const X509_REVOKED * r)468 const ASN1_INTEGER* X509_REVOKED_get0_serialNumber(const X509_REVOKED* r) {
469   return r->serialNumber;
470 }
471 
X509_REVOKED_get0_revocationDate(const X509_REVOKED * r)472 const ASN1_TIME* X509_REVOKED_get0_revocationDate(const X509_REVOKED* r) {
473   return r->revocationDate;
474 }
475 
X509_get_extension_flags(X509 * x)476 uint32_t X509_get_extension_flags(X509* x) {
477   // Tells OpenSSL to load flags
478   X509_check_purpose(x, -1, -1);
479   return x->ex_flags;
480 }
481 
X509_get_key_usage(X509 * x)482 uint32_t X509_get_key_usage(X509* x) {
483   // Call get_extension_flags rather than accessing directly to force loading
484   // of flags
485   if ((X509_get_extension_flags(x) & EXFLAG_KUSAGE) == EXFLAG_KUSAGE) {
486     return x->ex_kusage;
487   }
488   return UINT32_MAX;
489 }
490 
X509_get_extended_key_usage(X509 * x)491 uint32_t X509_get_extended_key_usage(X509* x) {
492   return x->ex_xkusage;
493 }
494 
X509_OBJECT_get_type(const X509_OBJECT * obj)495 int X509_OBJECT_get_type(const X509_OBJECT* obj) {
496   return obj->type;
497 }
498 
X509_OBJECT_get0_X509(const X509_OBJECT * obj)499 X509* X509_OBJECT_get0_X509(const X509_OBJECT* obj) {
500   if (obj == nullptr || obj->type != X509_LU_X509) {
501     return nullptr;
502   }
503   return obj->data.x509;
504 }
505 
X509_CRL_get0_lastUpdate(const X509_CRL * crl)506 const ASN1_TIME* X509_CRL_get0_lastUpdate(const X509_CRL* crl) {
507   return X509_CRL_get_lastUpdate(crl);
508 }
509 
X509_CRL_get0_nextUpdate(const X509_CRL * crl)510 const ASN1_TIME* X509_CRL_get0_nextUpdate(const X509_CRL* crl) {
511   return X509_CRL_get_nextUpdate(crl);
512 }
513 
X509_get0_tbs_sigalg(const X509 * x)514 const X509_ALGOR* X509_get0_tbs_sigalg(const X509* x) {
515   return x->cert_info->signature;
516 }
517 
518 #endif // !FOLLY_OPENSSL_IS_110
519 } // namespace ssl
520 } // namespace portability
521 } // namespace folly
522