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