Mercurial > hg > nginx
comparison src/event/ngx_event_quic_protection.c @ 8319:29354c6fc5f2 quic
TLS Key Update in QUIC.
Old keys retention is yet to be implemented.
author | Sergey Kandaurov <pluknet@nginx.com> |
---|---|
date | Mon, 06 Apr 2020 14:54:08 +0300 |
parents | 1bb5e8538d0c |
children | 7cca3624f9c4 |
comparison
equal
deleted
inserted
replaced
8318:1bb5e8538d0c | 8319:29354c6fc5f2 |
---|---|
230 { | 230 { |
231 size_t info_len; | 231 size_t info_len; |
232 uint8_t *p; | 232 uint8_t *p; |
233 uint8_t info[20]; | 233 uint8_t info[20]; |
234 | 234 |
235 out->data = ngx_pnalloc(pool, out->len); | |
236 if (out->data == NULL) { | 235 if (out->data == NULL) { |
237 return NGX_ERROR; | 236 out->data = ngx_pnalloc(pool, out->len); |
237 if (out->data == NULL) { | |
238 return NGX_ERROR; | |
239 } | |
238 } | 240 } |
239 | 241 |
240 info_len = 2 + 1 + label->len + 1; | 242 info_len = 2 + 1 + label->len + 1; |
241 | 243 |
242 info[0] = 0; | 244 info[0] = 0; |
619 } | 621 } |
620 | 622 |
621 if (level == ssl_encryption_initial) { | 623 if (level == ssl_encryption_initial) { |
622 return 0; | 624 return 0; |
623 } | 625 } |
626 | |
627 peer_secret->secret.data = ngx_pnalloc(pool, secret_len); | |
628 if (peer_secret->secret.data == NULL) { | |
629 return NGX_ERROR; | |
630 } | |
631 | |
632 peer_secret->secret.len = secret_len; | |
633 ngx_memcpy(peer_secret->secret.data, secret, secret_len); | |
624 | 634 |
625 peer_secret->key.len = key_len; | 635 peer_secret->key.len = key_len; |
626 peer_secret->iv.len = NGX_QUIC_IV_LEN; | 636 peer_secret->iv.len = NGX_QUIC_IV_LEN; |
627 peer_secret->hp.len = key_len; | 637 peer_secret->hp.len = key_len; |
628 | 638 |
648 | 658 |
649 return 1; | 659 return 1; |
650 } | 660 } |
651 | 661 |
652 | 662 |
663 ngx_int_t | |
664 ngx_quic_key_update(ngx_connection_t *c, ngx_quic_secrets_t *current, | |
665 ngx_quic_secrets_t *next) | |
666 { | |
667 ngx_uint_t i; | |
668 ngx_quic_ciphers_t ciphers; | |
669 | |
670 ngx_log_debug(NGX_LOG_DEBUG_EVENT, c->log, 0, "quic key update"); | |
671 | |
672 if (ngx_quic_ciphers(c->ssl->connection, &ciphers, | |
673 ssl_encryption_application) | |
674 == NGX_ERROR) | |
675 { | |
676 return NGX_ERROR; | |
677 } | |
678 | |
679 next->client.secret.len = current->client.secret.len; | |
680 next->client.key.len = current->client.key.len; | |
681 next->client.iv.len = current->client.iv.len; | |
682 next->client.hp = current->client.hp; | |
683 | |
684 next->server.secret.len = current->server.secret.len; | |
685 next->server.key.len = current->server.key.len; | |
686 next->server.iv.len = current->server.iv.len; | |
687 next->server.hp = current->server.hp; | |
688 | |
689 struct { | |
690 ngx_str_t label; | |
691 ngx_str_t *key; | |
692 ngx_str_t *secret; | |
693 } seq[] = { | |
694 { | |
695 ngx_string("tls13 quic ku"), | |
696 &next->client.secret, | |
697 ¤t->client.secret, | |
698 }, | |
699 { | |
700 ngx_string("tls13 quic key"), | |
701 &next->client.key, | |
702 &next->client.secret, | |
703 }, | |
704 { | |
705 ngx_string("tls13 quic iv"), | |
706 &next->client.iv, | |
707 &next->client.secret, | |
708 }, | |
709 { | |
710 ngx_string("tls13 quic ku"), | |
711 &next->server.secret, | |
712 ¤t->server.secret, | |
713 }, | |
714 { | |
715 ngx_string("tls13 quic key"), | |
716 &next->server.key, | |
717 &next->server.secret, | |
718 }, | |
719 { | |
720 ngx_string("tls13 quic iv"), | |
721 &next->server.iv, | |
722 &next->server.secret, | |
723 }, | |
724 }; | |
725 | |
726 for (i = 0; i < (sizeof(seq) / sizeof(seq[0])); i++) { | |
727 | |
728 if (ngx_quic_hkdf_expand(c->pool, ciphers.d, seq[i].key, &seq[i].label, | |
729 seq[i].secret->data, seq[i].secret->len) | |
730 != NGX_OK) | |
731 { | |
732 return NGX_ERROR; | |
733 } | |
734 } | |
735 | |
736 return NGX_OK; | |
737 } | |
738 | |
739 | |
653 static ssize_t | 740 static ssize_t |
654 ngx_quic_create_long_packet(ngx_quic_header_t *pkt, ngx_ssl_conn_t *ssl_conn, | 741 ngx_quic_create_long_packet(ngx_quic_header_t *pkt, ngx_ssl_conn_t *ssl_conn, |
655 ngx_str_t *res) | 742 ngx_str_t *res) |
656 { | 743 { |
657 u_char *pnp, *sample; | 744 u_char *pnp, *sample; |
819 ngx_int_t | 906 ngx_int_t |
820 ngx_quic_decrypt(ngx_quic_header_t *pkt, ngx_ssl_conn_t *ssl_conn) | 907 ngx_quic_decrypt(ngx_quic_header_t *pkt, ngx_ssl_conn_t *ssl_conn) |
821 { | 908 { |
822 u_char clearflags, *p, *sample; | 909 u_char clearflags, *p, *sample; |
823 uint64_t pn; | 910 uint64_t pn; |
824 ngx_int_t pnl, rc; | 911 ngx_int_t pnl, rc, key_phase; |
825 ngx_str_t in, ad; | 912 ngx_str_t in, ad; |
913 ngx_quic_secret_t *secret; | |
826 ngx_quic_ciphers_t ciphers; | 914 ngx_quic_ciphers_t ciphers; |
827 uint8_t mask[16], nonce[12]; | 915 uint8_t mask[16], nonce[12]; |
828 | 916 |
829 if (ngx_quic_ciphers(ssl_conn, &ciphers, pkt->level) == NGX_ERROR) { | 917 if (ngx_quic_ciphers(ssl_conn, &ciphers, pkt->level) == NGX_ERROR) { |
830 return NGX_ERROR; | 918 return NGX_ERROR; |
831 } | 919 } |
920 | |
921 secret = pkt->secret; | |
832 | 922 |
833 p = pkt->raw->pos; | 923 p = pkt->raw->pos; |
834 | 924 |
835 /* draft-ietf-quic-tls-23#section-5.4.2: | 925 /* draft-ietf-quic-tls-23#section-5.4.2: |
836 * the Packet Number field is assumed to be 4 bytes long | 926 * the Packet Number field is assumed to be 4 bytes long |
842 | 932 |
843 ngx_quic_hexdump0(pkt->log, "sample", sample, 16); | 933 ngx_quic_hexdump0(pkt->log, "sample", sample, 16); |
844 | 934 |
845 /* header protection */ | 935 /* header protection */ |
846 | 936 |
847 if (ngx_quic_tls_hp(pkt->log, ciphers.hp, pkt->secret, mask, sample) | 937 if (ngx_quic_tls_hp(pkt->log, ciphers.hp, secret, mask, sample) |
848 != NGX_OK) | 938 != NGX_OK) |
849 { | 939 { |
850 return NGX_ERROR; | 940 return NGX_ERROR; |
851 } | 941 } |
852 | 942 |
853 if (ngx_quic_long_pkt(pkt->flags)) { | 943 if (ngx_quic_long_pkt(pkt->flags)) { |
854 clearflags = pkt->flags ^ (mask[0] & 0x0f); | 944 clearflags = pkt->flags ^ (mask[0] & 0x0f); |
855 | 945 |
856 } else { | 946 } else { |
857 clearflags = pkt->flags ^ (mask[0] & 0x1f); | 947 clearflags = pkt->flags ^ (mask[0] & 0x1f); |
948 key_phase = (clearflags & NGX_QUIC_PKT_KPHASE) != 0; | |
949 | |
950 if (key_phase != pkt->key_phase) { | |
951 secret = pkt->next; | |
952 pkt->key_update = 1; | |
953 } | |
858 } | 954 } |
859 | 955 |
860 pnl = (clearflags & 0x03) + 1; | 956 pnl = (clearflags & 0x03) + 1; |
861 pn = ngx_quic_parse_pn(&p, pnl, &mask[1]); | 957 pn = ngx_quic_parse_pn(&p, pnl, &mask[1]); |
862 | 958 |
887 | 983 |
888 do { | 984 do { |
889 ad.data[ad.len - pnl] = pn >> (8 * (pnl - 1)) % 256; | 985 ad.data[ad.len - pnl] = pn >> (8 * (pnl - 1)) % 256; |
890 } while (--pnl); | 986 } while (--pnl); |
891 | 987 |
892 ngx_memcpy(nonce, pkt->secret->iv.data, pkt->secret->iv.len); | 988 ngx_memcpy(nonce, secret->iv.data, secret->iv.len); |
893 ngx_quic_compute_nonce(nonce, sizeof(nonce), pn); | 989 ngx_quic_compute_nonce(nonce, sizeof(nonce), pn); |
894 | 990 |
895 ngx_quic_hexdump0(pkt->log, "nonce", nonce, 12); | 991 ngx_quic_hexdump0(pkt->log, "nonce", nonce, 12); |
896 ngx_quic_hexdump0(pkt->log, "ad", ad.data, ad.len); | 992 ngx_quic_hexdump0(pkt->log, "ad", ad.data, ad.len); |
897 | 993 |
901 return NGX_ERROR; | 997 return NGX_ERROR; |
902 } | 998 } |
903 | 999 |
904 pkt->payload.data = pkt->plaintext + ad.len; | 1000 pkt->payload.data = pkt->plaintext + ad.len; |
905 | 1001 |
906 rc = ngx_quic_tls_open(ciphers.c, pkt->secret, &pkt->payload, | 1002 rc = ngx_quic_tls_open(ciphers.c, secret, &pkt->payload, |
907 nonce, &in, &ad, pkt->log); | 1003 nonce, &in, &ad, pkt->log); |
908 | 1004 |
909 ngx_quic_hexdump0(pkt->log, "packet payload", | 1005 ngx_quic_hexdump0(pkt->log, "packet payload", |
910 pkt->payload.data, pkt->payload.len); | 1006 pkt->payload.data, pkt->payload.len); |
911 | 1007 |