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