Deleted Added
1
2/*
3 * Copyright (C) Igor Sysoev
4 * Copyright (C) NGINX, Inc.
5 */
6
7#include <nxt_main.h>
8#include <nxt_conf.h>
9#include <openssl/ssl.h>
10#include <openssl/conf.h>
11#include <openssl/err.h>
12#include <openssl/rand.h>
13#include <openssl/x509v3.h>
14#include <openssl/bio.h>
15#include <openssl/evp.h>
16
17
18typedef struct {
19 SSL *session;
20 nxt_conn_t *conn;
21
22 int ssl_error;
23 uint8_t times; /* 2 bits */

--- 23 unchanged lines hidden (view full) ---

47static nxt_int_t nxt_openssl_server_init(nxt_task_t *task, nxt_mp_t *mp,
48 nxt_tls_init_t *tls_init, nxt_bool_t last);
49static nxt_int_t nxt_openssl_chain_file(nxt_task_t *task, SSL_CTX *ctx,
50 nxt_tls_conf_t *conf, nxt_mp_t *mp, nxt_bool_t single);
51#if (NXT_HAVE_OPENSSL_CONF_CMD)
52static nxt_int_t nxt_ssl_conf_commands(nxt_task_t *task, SSL_CTX *ctx,
53 nxt_conf_value_t *value, nxt_mp_t *mp);
54#endif
55#if (NXT_HAVE_OPENSSL_TLSEXT)
56static nxt_int_t nxt_tls_ticket_keys(nxt_task_t *task, SSL_CTX *ctx,
57 nxt_tls_init_t *tls_init, nxt_mp_t *mp);
58static int nxt_tls_ticket_key_callback(SSL *s, unsigned char *name,
59 unsigned char *iv, EVP_CIPHER_CTX *ectx,HMAC_CTX *hctx, int enc);
60#endif
61static void nxt_ssl_session_cache(SSL_CTX *ctx, size_t cache_size,
62 time_t timeout);
63static nxt_uint_t nxt_openssl_cert_get_names(nxt_task_t *task, X509 *cert,
64 nxt_tls_conf_t *conf, nxt_mp_t *mp);
65static nxt_int_t nxt_openssl_bundle_hash_test(nxt_lvlhsh_query_t *lhq,
66 void *data);
67static nxt_int_t nxt_openssl_bundle_hash_insert(nxt_task_t *task,
68 nxt_lvlhsh_t *lvlhsh, nxt_tls_bundle_hash_item_t *item, nxt_mp_t * mp);

--- 284 unchanged lines hidden (view full) ---

353 && nxt_ssl_conf_commands(task, ctx, tls_init->conf_cmds, mp) != NXT_OK)
354 {
355 goto fail;
356 }
357#endif
358
359 nxt_ssl_session_cache(ctx, tls_init->cache_size, tls_init->timeout);
360
361#if (NXT_HAVE_OPENSSL_TLSEXT)
362 if (nxt_tls_ticket_keys(task, ctx, tls_init, mp) != NXT_OK) {
363 goto fail;
364 }
365#endif
366
367 SSL_CTX_set_options(ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
368
369 if (conf->ca_certificate != NULL) {
370
371 /* TODO: verify callback */
372 SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
373
374 /* TODO: verify depth */

--- 221 unchanged lines hidden (view full) ---

596
597 SSL_CONF_CTX_free(cctx);
598
599 return NXT_ERROR;
600}
601
602#endif
603
604#if (NXT_HAVE_OPENSSL_TLSEXT)
605
606static nxt_int_t
607nxt_tls_ticket_keys(nxt_task_t *task, SSL_CTX *ctx, nxt_tls_init_t *tls_init,
608 nxt_mp_t *mp)
609{
610 uint32_t i;
611 nxt_int_t ret;
612 nxt_str_t value;
613 nxt_uint_t count;
614 nxt_conf_value_t *member, *tickets_conf;
615 nxt_tls_ticket_t *ticket;
616 nxt_tls_tickets_t *tickets;
617 u_char buf[80];
618
619 tickets_conf = tls_init->tickets_conf;
620
621 if (tickets_conf == NULL) {
622 goto no_ticket;
623 }
624
625 if (nxt_conf_type(tickets_conf) == NXT_CONF_BOOLEAN) {
626 if (nxt_conf_get_boolean(tickets_conf) == 0) {
627 goto no_ticket;
628 }
629
630 return NXT_OK;
631 }
632
633 if (nxt_conf_type(tickets_conf) == NXT_CONF_ARRAY) {
634 count = nxt_conf_array_elements_count(tickets_conf);
635
636 if (count == 0) {
637 goto no_ticket;
638 }
639
640 } else {
641 /* nxt_conf_type(tickets_conf) == NXT_CONF_STRING */
642 count = 1;
643 }
644
645#ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB
646
647 tickets = nxt_mp_get(mp, sizeof(nxt_tls_tickets_t)
648 + count * sizeof(nxt_tls_ticket_t));
649 if (nxt_slow_path(tickets == NULL)) {
650 return NXT_ERROR;
651 }
652
653 tickets->count = count;
654 tls_init->conf->tickets = tickets;
655 i = 0;
656
657 do {
658 ticket = &tickets->tickets[i];
659
660 i++;
661
662 if (nxt_conf_type(tickets_conf) == NXT_CONF_ARRAY) {
663 member = nxt_conf_get_array_element(tickets_conf, count - i);
664 if (member == NULL) {
665 break;
666 }
667
668 } else {
669 /* nxt_conf_type(tickets_conf) == NXT_CONF_STRING */
670 member = tickets_conf;
671 }
672
673 nxt_conf_get_string(member, &value);
674
675 ret = nxt_openssl_base64_decode(buf, 80, value.start, value.length);
676 if (nxt_slow_path(ret == NXT_ERROR)) {
677 return NXT_ERROR;
678 }
679
680 if (ret == 48) {
681 ticket->aes128 = 1;
682 nxt_memcpy(ticket->aes_key, buf + 16, 16);
683 nxt_memcpy(ticket->hmac_key, buf + 32, 16);
684
685 } else {
686 ticket->aes128 = 0;
687 nxt_memcpy(ticket->hmac_key, buf + 16, 32);
688 nxt_memcpy(ticket->aes_key, buf + 48, 32);
689 }
690
691 nxt_memcpy(ticket->name, buf, 16);
692 } while (i < count);
693
694 if (SSL_CTX_set_tlsext_ticket_key_cb(ctx, nxt_tls_ticket_key_callback)
695 == 0)
696 {
697 nxt_openssl_log_error(task, NXT_LOG_ALERT,
698 "Unit was built with Session Tickets support, however, "
699 "now it is linked dynamically to an OpenSSL library "
700 "which has no tlsext support, therefore Session Tickets "
701 "are not available");
702
703 return NXT_ERROR;
704 }
705
706 return NXT_OK;
707
708#else
709 nxt_alert(task, "Setting custom session ticket keys is not supported with "
710 "this version of OpenSSL library");
711
712 return NXT_ERROR;
713
714#endif
715
716no_ticket:
717
718 SSL_CTX_set_options(ctx, SSL_OP_NO_TICKET);
719
720 return NXT_OK;
721}
722
723
724#ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB
725
726static int
727nxt_tls_ticket_key_callback(SSL *s, unsigned char *name, unsigned char *iv,
728 EVP_CIPHER_CTX *ectx, HMAC_CTX *hctx, int enc)
729{
730 size_t size;
731 nxt_uint_t i;
732 nxt_conn_t *c;
733 const EVP_MD *digest;
734 const EVP_CIPHER *cipher;
735 nxt_tls_ticket_t *ticket;
736 nxt_openssl_conn_t *tls;
737
738 c = SSL_get_ex_data(s, nxt_openssl_connection_index);
739
740 if (nxt_slow_path(c == NULL)) {
741 nxt_thread_log_alert("SSL_get_ex_data() failed");
742 return -1;
743 }
744
745 tls = c->u.tls;
746 ticket = tls->conf->tickets->tickets;
747
748#ifdef OPENSSL_NO_SHA256
749 digest = EVP_sha1();
750#else
751 digest = EVP_sha256();
752#endif
753
754 if (enc == 1) {
755 /* encrypt session ticket */
756
757 nxt_debug(c->socket.task, "TLS session ticket encrypt");
758
759 if (ticket[0].aes128 == 1) {
760 cipher = EVP_aes_128_cbc();
761 size = 16;
762
763 } else {
764 cipher = EVP_aes_256_cbc();
765 size = 32;
766 }
767
768 if (RAND_bytes(iv, EVP_CIPHER_iv_length(cipher)) != 1) {
769 nxt_openssl_log_error(c->socket.task, NXT_LOG_ALERT,
770 "RAND_bytes() failed");
771 return -1;
772 }
773
774 if (EVP_EncryptInit_ex(ectx, cipher, NULL, ticket[0].aes_key, iv)
775 != 1)
776 {
777 nxt_openssl_log_error(c->socket.task, NXT_LOG_ALERT,
778 "EVP_EncryptInit_ex() failed");
779 return -1;
780 }
781
782 if (HMAC_Init_ex(hctx, ticket[0].hmac_key, size, digest, NULL) != 1) {
783 nxt_openssl_log_error(c->socket.task, NXT_LOG_ALERT,
784 "HMAC_Init_ex() failed");
785 return -1;
786 }
787
788 nxt_memcpy(name, ticket[0].name, 16);
789
790 return 1;
791
792 } else {
793 /* decrypt session ticket */
794
795 for (i = 0; i < tls->conf->tickets->count; i++) {
796 if (nxt_memcmp(name, ticket[i].name, 16) == 0) {
797 goto found;
798 }
799 }
800
801 nxt_debug(c->socket.task, "TLS session ticket decrypt, key not found");
802
803 return 0;
804
805 found:
806
807 nxt_debug(c->socket.task,
808 "TLS session ticket decrypt, key number: \"%d\"", i);
809
810 if (ticket[i].aes128 == 1) {
811 cipher = EVP_aes_128_cbc();
812 size = 16;
813
814 } else {
815 cipher = EVP_aes_256_cbc();
816 size = 32;
817 }
818
819 if (EVP_DecryptInit_ex(ectx, cipher, NULL, ticket[i].aes_key, iv) != 1) {
820 nxt_openssl_log_error(c->socket.task, NXT_LOG_ALERT,
821 "EVP_DecryptInit_ex() failed");
822 return -1;
823 }
824
825 if (HMAC_Init_ex(hctx, ticket[i].hmac_key, size, digest, NULL) != 1) {
826 nxt_openssl_log_error(c->socket.task, NXT_LOG_ALERT,
827 "HMAC_Init_ex() failed");
828 return -1;
829 }
830
831 return (i == 0) ? 1 : 2 /* renew */;
832 }
833}
834
835#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
836
837#endif /* NXT_HAVE_OPENSSL_TLSEXT */
838
839
840static void
841nxt_ssl_session_cache(SSL_CTX *ctx, size_t cache_size, time_t timeout)
842{
843 if (cache_size == 0) {
844 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
845 return;
846 }
847

--- 300 unchanged lines hidden (view full) ---

1148 bundle = conf->bundle;
1149 nxt_assert(bundle != NULL);
1150
1151 do {
1152 SSL_CTX_free(bundle->ctx);
1153 bundle = bundle->next;
1154 } while (bundle != NULL);
1155
1156 if (conf->tickets) {
1157 nxt_memzero(conf->tickets->tickets,
1158 conf->tickets->count * sizeof(nxt_tls_ticket_t));
1159 }
1160
1161#if (OPENSSL_VERSION_NUMBER >= 0x1010100fL \
1162 && OPENSSL_VERSION_NUMBER < 0x1010101fL)
1163 RAND_keep_random_devices_open(0);
1164#endif
1165}
1166
1167
1168static void

--- 645 unchanged lines hidden (view full) ---

1814 }
1815
1816 if (p < end) {
1817 *p++ = ')';
1818 }
1819
1820 return p;
1821}
1822
1823
1824nxt_int_t
1825nxt_openssl_base64_decode(u_char *d, size_t dlen, const u_char *s, size_t slen)
1826{
1827 BIO *bio, *b64;
1828 nxt_int_t count, ret;
1829 u_char buf[128];
1830
1831 b64 = BIO_new(BIO_f_base64());
1832 if (nxt_slow_path(b64 == NULL)) {
1833 goto error;
1834 }
1835
1836 bio = BIO_new_mem_buf(s, slen);
1837 if (nxt_slow_path(bio == NULL)) {
1838 goto error;
1839 }
1840
1841 bio = BIO_push(b64, bio);
1842
1843 BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL);
1844
1845 count = 0;
1846
1847 if (d == NULL) {
1848
1849 for ( ;; ) {
1850 ret = BIO_read(bio, buf, 128);
1851
1852 if (ret < 0) {
1853 goto invalid;
1854 }
1855
1856 count += ret;
1857
1858 if (ret != 128) {
1859 break;
1860 }
1861 }
1862
1863 } else {
1864 count = BIO_read(bio, d, dlen);
1865
1866 if (count < 0) {
1867 goto invalid;
1868 }
1869 }
1870
1871 BIO_free_all(bio);
1872
1873 return count;
1874
1875error:
1876
1877 BIO_vfree(b64);
1878 ERR_clear_error();
1879
1880 return NXT_ERROR;
1881
1882invalid:
1883
1884 BIO_free_all(bio);
1885 ERR_clear_error();
1886
1887 return NXT_DECLINED;
1888}