comparison src/event/quic/ngx_event_quic.c @ 8752:e19723c40d28 quic

QUIC: separate files for tokens related processing.
author Vladimir Homutov <vl@nginx.com>
date Tue, 13 Apr 2021 14:41:52 +0300
parents bc910a5ec737
children 46161c610919
comparison
equal deleted inserted replaced
8751:bc910a5ec737 8752:e19723c40d28
5 5
6 6
7 #include <ngx_config.h> 7 #include <ngx_config.h>
8 #include <ngx_core.h> 8 #include <ngx_core.h>
9 #include <ngx_event.h> 9 #include <ngx_event.h>
10 #include <ngx_sha1.h>
11 #include <ngx_event_quic_connection.h> 10 #include <ngx_event_quic_connection.h>
12 11
13 12
14 /* 13 /*
15 * 7.4. Cryptographic Message Buffering 14 * 7.4. Cryptographic Message Buffering
40 ngx_quic_tp_t *ctp); 39 ngx_quic_tp_t *ctp);
41 static ngx_quic_connection_t *ngx_quic_new_connection(ngx_connection_t *c, 40 static ngx_quic_connection_t *ngx_quic_new_connection(ngx_connection_t *c,
42 ngx_quic_conf_t *conf, ngx_quic_header_t *pkt); 41 ngx_quic_conf_t *conf, ngx_quic_header_t *pkt);
43 static ngx_int_t ngx_quic_process_stateless_reset(ngx_connection_t *c, 42 static ngx_int_t ngx_quic_process_stateless_reset(ngx_connection_t *c,
44 ngx_quic_header_t *pkt); 43 ngx_quic_header_t *pkt);
45 static void ngx_quic_address_hash(ngx_connection_t *c, ngx_uint_t no_port,
46 u_char buf[20]);
47 static ngx_int_t ngx_quic_validate_token(ngx_connection_t *c,
48 u_char *key, ngx_quic_header_t *pkt);
49 static ngx_int_t ngx_quic_init_connection(ngx_connection_t *c); 44 static ngx_int_t ngx_quic_init_connection(ngx_connection_t *c);
50 static void ngx_quic_input_handler(ngx_event_t *rev); 45 static void ngx_quic_input_handler(ngx_event_t *rev);
51 46
52 static ngx_int_t ngx_quic_close_quic(ngx_connection_t *c, ngx_int_t rc); 47 static ngx_int_t ngx_quic_close_quic(ngx_connection_t *c, ngx_int_t rc);
53 static void ngx_quic_close_timer_handler(ngx_event_t *ev); 48 static void ngx_quic_close_timer_handler(ngx_event_t *ev);
618 613
619 return qc; 614 return qc;
620 } 615 }
621 616
622 617
623 ngx_int_t
624 ngx_quic_new_sr_token(ngx_connection_t *c, ngx_str_t *cid, u_char *secret,
625 u_char *token)
626 {
627 ngx_str_t tmp;
628
629 tmp.data = secret;
630 tmp.len = NGX_QUIC_SR_KEY_LEN;
631
632 if (ngx_quic_derive_key(c->log, "sr_token_key", &tmp, cid, token,
633 NGX_QUIC_SR_TOKEN_LEN)
634 != NGX_OK)
635 {
636 return NGX_ERROR;
637 }
638
639 #if (NGX_DEBUG)
640 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
641 "quic stateless reset token %*xs",
642 (size_t) NGX_QUIC_SR_TOKEN_LEN, token);
643 #endif
644
645 return NGX_OK;
646 }
647
648
649 static ngx_int_t 618 static ngx_int_t
650 ngx_quic_process_stateless_reset(ngx_connection_t *c, ngx_quic_header_t *pkt) 619 ngx_quic_process_stateless_reset(ngx_connection_t *c, ngx_quic_header_t *pkt)
651 { 620 {
652 u_char *tail, ch; 621 u_char *tail, ch;
653 ngx_uint_t i; 622 ngx_uint_t i;
683 652
684 if (ch == 0) { 653 if (ch == 0) {
685 return NGX_OK; 654 return NGX_OK;
686 } 655 }
687 } 656 }
688
689 return NGX_DECLINED;
690 }
691
692
693 ngx_int_t
694 ngx_quic_new_token(ngx_connection_t *c, u_char *key, ngx_str_t *token,
695 ngx_str_t *odcid, time_t exp, ngx_uint_t is_retry)
696 {
697 int len, iv_len;
698 u_char *p, *iv;
699 EVP_CIPHER_CTX *ctx;
700 const EVP_CIPHER *cipher;
701
702 u_char in[NGX_QUIC_MAX_TOKEN_SIZE];
703
704 ngx_quic_address_hash(c, !is_retry, in);
705
706 p = in + 20;
707
708 p = ngx_cpymem(p, &exp, sizeof(time_t));
709
710 *p++ = is_retry ? 1 : 0;
711
712 if (odcid) {
713 *p++ = odcid->len;
714 p = ngx_cpymem(p, odcid->data, odcid->len);
715
716 } else {
717 *p++ = 0;
718 }
719
720 len = p - in;
721
722 cipher = EVP_aes_256_cbc();
723 iv_len = EVP_CIPHER_iv_length(cipher);
724
725 token->len = iv_len + len + EVP_CIPHER_block_size(cipher);
726 token->data = ngx_pnalloc(c->pool, token->len);
727 if (token->data == NULL) {
728 return NGX_ERROR;
729 }
730
731 ctx = EVP_CIPHER_CTX_new();
732 if (ctx == NULL) {
733 return NGX_ERROR;
734 }
735
736 iv = token->data;
737
738 if (RAND_bytes(iv, iv_len) <= 0
739 || !EVP_EncryptInit_ex(ctx, cipher, NULL, key, iv))
740 {
741 EVP_CIPHER_CTX_free(ctx);
742 return NGX_ERROR;
743 }
744
745 token->len = iv_len;
746
747 if (EVP_EncryptUpdate(ctx, token->data + token->len, &len, in, len) != 1) {
748 EVP_CIPHER_CTX_free(ctx);
749 return NGX_ERROR;
750 }
751
752 token->len += len;
753
754 if (EVP_EncryptFinal_ex(ctx, token->data + token->len, &len) <= 0) {
755 EVP_CIPHER_CTX_free(ctx);
756 return NGX_ERROR;
757 }
758
759 token->len += len;
760
761 EVP_CIPHER_CTX_free(ctx);
762
763 #ifdef NGX_QUIC_DEBUG_PACKETS
764 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
765 "quic new token len:%uz %xV", token->len, token);
766 #endif
767
768 return NGX_OK;
769 }
770
771
772 static void
773 ngx_quic_address_hash(ngx_connection_t *c, ngx_uint_t no_port, u_char buf[20])
774 {
775 size_t len;
776 u_char *data;
777 ngx_sha1_t sha1;
778 struct sockaddr_in *sin;
779 #if (NGX_HAVE_INET6)
780 struct sockaddr_in6 *sin6;
781 #endif
782
783 len = (size_t) c->socklen;
784 data = (u_char *) c->sockaddr;
785
786 if (no_port) {
787 switch (c->sockaddr->sa_family) {
788
789 #if (NGX_HAVE_INET6)
790 case AF_INET6:
791 sin6 = (struct sockaddr_in6 *) c->sockaddr;
792
793 len = sizeof(struct in6_addr);
794 data = sin6->sin6_addr.s6_addr;
795
796 break;
797 #endif
798
799 case AF_INET:
800 sin = (struct sockaddr_in *) c->sockaddr;
801
802 len = sizeof(in_addr_t);
803 data = (u_char *) &sin->sin_addr;
804
805 break;
806 }
807 }
808
809 ngx_sha1_init(&sha1);
810 ngx_sha1_update(&sha1, data, len);
811 ngx_sha1_final(buf, &sha1);
812 }
813
814
815 static ngx_int_t
816 ngx_quic_validate_token(ngx_connection_t *c, u_char *key,
817 ngx_quic_header_t *pkt)
818 {
819 int len, tlen, iv_len;
820 u_char *iv, *p;
821 time_t now, exp;
822 size_t total;
823 ngx_str_t odcid;
824 EVP_CIPHER_CTX *ctx;
825 const EVP_CIPHER *cipher;
826
827 u_char addr_hash[20];
828 u_char tdec[NGX_QUIC_MAX_TOKEN_SIZE];
829
830 /* Retry token or NEW_TOKEN in a previous connection */
831
832 cipher = EVP_aes_256_cbc();
833 iv = pkt->token.data;
834 iv_len = EVP_CIPHER_iv_length(cipher);
835
836 /* sanity checks */
837
838 if (pkt->token.len < (size_t) iv_len + EVP_CIPHER_block_size(cipher)) {
839 goto garbage;
840 }
841
842 if (pkt->token.len > (size_t) iv_len + NGX_QUIC_MAX_TOKEN_SIZE) {
843 goto garbage;
844 }
845
846 ctx = EVP_CIPHER_CTX_new();
847 if (ctx == NULL) {
848 return NGX_ERROR;
849 }
850
851 if (!EVP_DecryptInit_ex(ctx, cipher, NULL, key, iv)) {
852 EVP_CIPHER_CTX_free(ctx);
853 return NGX_ERROR;
854 }
855
856 p = pkt->token.data + iv_len;
857 len = pkt->token.len - iv_len;
858
859 if (EVP_DecryptUpdate(ctx, tdec, &len, p, len) != 1) {
860 EVP_CIPHER_CTX_free(ctx);
861 goto garbage;
862 }
863 total = len;
864
865 if (EVP_DecryptFinal_ex(ctx, tdec + len, &tlen) <= 0) {
866 EVP_CIPHER_CTX_free(ctx);
867 goto garbage;
868 }
869 total += tlen;
870
871 EVP_CIPHER_CTX_free(ctx);
872
873 if (total < (20 + sizeof(time_t) + 2)) {
874 goto garbage;
875 }
876
877 p = tdec + 20;
878
879 ngx_memcpy(&exp, p, sizeof(time_t));
880 p += sizeof(time_t);
881
882 pkt->retried = (*p++ == 1);
883
884 ngx_quic_address_hash(c, !pkt->retried, addr_hash);
885
886 if (ngx_memcmp(tdec, addr_hash, 20) != 0) {
887 goto bad_token;
888 }
889
890 odcid.len = *p++;
891 if (odcid.len) {
892 if (odcid.len > NGX_QUIC_MAX_CID_LEN) {
893 goto bad_token;
894 }
895
896 if ((size_t)(tdec + total - p) < odcid.len) {
897 goto bad_token;
898 }
899
900 odcid.data = p;
901 p += odcid.len;
902 }
903
904 now = ngx_time();
905
906 if (now > exp) {
907 ngx_log_error(NGX_LOG_INFO, c->log, 0, "quic expired token");
908 return NGX_DECLINED;
909 }
910
911 if (odcid.len) {
912 pkt->odcid.len = odcid.len;
913 pkt->odcid.data = ngx_pstrdup(c->pool, &odcid);
914 if (pkt->odcid.data == NULL) {
915 return NGX_ERROR;
916 }
917
918 } else {
919 pkt->odcid = pkt->dcid;
920 }
921
922 pkt->validated = 1;
923
924 return NGX_OK;
925
926 garbage:
927
928 ngx_log_error(NGX_LOG_INFO, c->log, 0, "quic garbage token");
929
930 return NGX_ABORT;
931
932 bad_token:
933
934 ngx_log_error(NGX_LOG_INFO, c->log, 0, "quic invalid token");
935 657
936 return NGX_DECLINED; 658 return NGX_DECLINED;
937 } 659 }
938 660
939 661