diff options
author | jsing <> | 2020-07-30 16:53:01 +0000 |
---|---|---|
committer | jsing <> | 2020-07-30 16:53:01 +0000 |
commit | 8ff4976278b8287ec84e713ef782be6f4989ce06 (patch) | |
tree | 2261e7d086b3d5261d8ee4bae427be3d75698dd4 /src/lib/libssl/ssl_pkt.c | |
parent | c83de9bf1a5deaa83030eac8eb7a2ce4749d120d (diff) | |
download | openbsd-8ff4976278b8287ec84e713ef782be6f4989ce06.tar.gz openbsd-8ff4976278b8287ec84e713ef782be6f4989ce06.tar.bz2 openbsd-8ff4976278b8287ec84e713ef782be6f4989ce06.zip |
Clean up and simplify some of the SSL3/DTLS1 record writing code.
This will allow for further changes to be made with less complexity and
easier review.
In particular, decide if we need an empty fragment early on and only do
the alignment calculation once (rather than in two separate parts of the
function.
ok tb@ inoguchi@
Diffstat (limited to 'src/lib/libssl/ssl_pkt.c')
-rw-r--r-- | src/lib/libssl/ssl_pkt.c | 115 |
1 files changed, 58 insertions, 57 deletions
diff --git a/src/lib/libssl/ssl_pkt.c b/src/lib/libssl/ssl_pkt.c index 157dd9895b..02282778a2 100644 --- a/src/lib/libssl/ssl_pkt.c +++ b/src/lib/libssl/ssl_pkt.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssl_pkt.c,v 1.24 2020/03/16 15:25:14 tb Exp $ */ | 1 | /* $OpenBSD: ssl_pkt.c,v 1.25 2020/07/30 16:53:01 jsing Exp $ */ |
2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
3 | * All rights reserved. | 3 | * All rights reserved. |
4 | * | 4 | * |
@@ -622,18 +622,15 @@ ssl3_create_record(SSL *s, unsigned char *p, int type, const unsigned char *buf, | |||
622 | { | 622 | { |
623 | SSL3_RECORD_INTERNAL *wr = &(S3I(s)->wrec); | 623 | SSL3_RECORD_INTERNAL *wr = &(S3I(s)->wrec); |
624 | SSL_SESSION *sess = s->session; | 624 | SSL_SESSION *sess = s->session; |
625 | int eivlen, mac_size; | 625 | int eivlen, mac_size = 0; |
626 | uint16_t version; | 626 | uint16_t version; |
627 | CBB cbb; | 627 | CBB cbb; |
628 | 628 | ||
629 | memset(&cbb, 0, sizeof(cbb)); | 629 | memset(&cbb, 0, sizeof(cbb)); |
630 | 630 | ||
631 | if ((sess == NULL) || (s->internal->enc_write_ctx == NULL) || | 631 | if (sess != NULL && s->internal->enc_write_ctx != NULL && |
632 | (EVP_MD_CTX_md(s->internal->write_hash) == NULL)) { | 632 | EVP_MD_CTX_md(s->internal->write_hash) != NULL) { |
633 | mac_size = 0; | 633 | if ((mac_size = EVP_MD_CTX_size(s->internal->write_hash)) < 0) |
634 | } else { | ||
635 | mac_size = EVP_MD_CTX_size(s->internal->write_hash); | ||
636 | if (mac_size < 0) | ||
637 | goto err; | 634 | goto err; |
638 | } | 635 | } |
639 | 636 | ||
@@ -682,9 +679,11 @@ ssl3_create_record(SSL *s, unsigned char *p, int type, const unsigned char *buf, | |||
682 | memcpy(wr->data, wr->input, wr->length); | 679 | memcpy(wr->data, wr->input, wr->length); |
683 | wr->input = wr->data; | 680 | wr->input = wr->data; |
684 | 681 | ||
685 | /* we should still have the output to wr->data and the input | 682 | /* |
683 | * We should still have the output to wr->data and the input | ||
686 | * from wr->input. Length should be wr->length. | 684 | * from wr->input. Length should be wr->length. |
687 | * wr->data still points in the wb->buf */ | 685 | * wr->data still points in the wb->buf. |
686 | */ | ||
688 | 687 | ||
689 | if (mac_size != 0) { | 688 | if (mac_size != 0) { |
690 | if (tls1_mac(s, &(p[wr->length + eivlen]), 1) < 0) | 689 | if (tls1_mac(s, &(p[wr->length + eivlen]), 1) < 0) |
@@ -732,26 +731,29 @@ do_ssl3_write(SSL *s, int type, const unsigned char *buf, unsigned int len) | |||
732 | SSL3_BUFFER_INTERNAL *wb = &(S3I(s)->wbuf); | 731 | SSL3_BUFFER_INTERNAL *wb = &(S3I(s)->wbuf); |
733 | SSL_SESSION *sess = s->session; | 732 | SSL_SESSION *sess = s->session; |
734 | unsigned char *p; | 733 | unsigned char *p; |
735 | int i, clear = 0; | 734 | int need_empty_fragment = 0; |
736 | int prefix_len = 0; | 735 | int prefix_len = 0; |
737 | size_t align; | 736 | size_t align; |
737 | int ret; | ||
738 | 738 | ||
739 | if (wb->buf == NULL) | 739 | if (wb->buf == NULL) |
740 | if (!ssl3_setup_write_buffer(s)) | 740 | if (!ssl3_setup_write_buffer(s)) |
741 | return -1; | 741 | return -1; |
742 | 742 | ||
743 | /* first check if there is a SSL3_BUFFER_INTERNAL still being written | 743 | /* |
744 | * out. This will happen with non blocking IO */ | 744 | * First check if there is a SSL3_BUFFER_INTERNAL still being written |
745 | * out. This will happen with non blocking IO. | ||
746 | */ | ||
745 | if (wb->left != 0) | 747 | if (wb->left != 0) |
746 | return (ssl3_write_pending(s, type, buf, len)); | 748 | return (ssl3_write_pending(s, type, buf, len)); |
747 | 749 | ||
748 | /* If we have an alert to send, lets send it */ | 750 | /* If we have an alert to send, let's send it. */ |
749 | if (S3I(s)->alert_dispatch) { | 751 | if (S3I(s)->alert_dispatch) { |
750 | i = s->method->ssl_dispatch_alert(s); | 752 | if ((ret = s->method->ssl_dispatch_alert(s)) <= 0) |
751 | if (i <= 0) | 753 | return (ret); |
752 | return (i); | 754 | /* If it went, fall through and send more stuff. */ |
753 | /* if it went, fall through and send more stuff */ | 755 | |
754 | /* we may have released our buffer, so get it again */ | 756 | /* We may have released our buffer, if so get it again. */ |
755 | if (wb->buf == NULL) | 757 | if (wb->buf == NULL) |
756 | if (!ssl3_setup_write_buffer(s)) | 758 | if (!ssl3_setup_write_buffer(s)) |
757 | return -1; | 759 | return -1; |
@@ -760,47 +762,44 @@ do_ssl3_write(SSL *s, int type, const unsigned char *buf, unsigned int len) | |||
760 | if (len == 0) | 762 | if (len == 0) |
761 | return 0; | 763 | return 0; |
762 | 764 | ||
765 | /* | ||
766 | * Countermeasure against known-IV weakness in CBC ciphersuites | ||
767 | * (see http://www.openssl.org/~bodo/tls-cbc.txt). Note that this | ||
768 | * is unnecessary for AEAD. | ||
769 | */ | ||
770 | if (sess != NULL && s->internal->enc_write_ctx != NULL && | ||
771 | EVP_MD_CTX_md(s->internal->write_hash) != NULL) { | ||
772 | if (S3I(s)->need_empty_fragments && | ||
773 | !S3I(s)->empty_fragment_done && | ||
774 | type == SSL3_RT_APPLICATION_DATA) | ||
775 | need_empty_fragment = 1; | ||
776 | } | ||
777 | |||
778 | /* | ||
779 | * An extra fragment would be a couple of cipher blocks, which would | ||
780 | * be a multiple of SSL3_ALIGN_PAYLOAD, so if we want to align the real | ||
781 | * payload, then we can just simply pretend we have two headers. | ||
782 | */ | ||
763 | align = (size_t)wb->buf + SSL3_RT_HEADER_LENGTH; | 783 | align = (size_t)wb->buf + SSL3_RT_HEADER_LENGTH; |
784 | if (need_empty_fragment) | ||
785 | align += SSL3_RT_HEADER_LENGTH; | ||
764 | align = (-align) & (SSL3_ALIGN_PAYLOAD - 1); | 786 | align = (-align) & (SSL3_ALIGN_PAYLOAD - 1); |
765 | 787 | ||
766 | p = wb->buf + align; | 788 | p = wb->buf + align; |
767 | wb->offset = align; | 789 | wb->offset = align; |
768 | 790 | ||
769 | if ((sess == NULL) || (s->internal->enc_write_ctx == NULL) || | 791 | if (need_empty_fragment) { |
770 | (EVP_MD_CTX_md(s->internal->write_hash) == NULL)) { | 792 | if (!ssl3_create_record(s, p, type, buf, 0)) |
771 | clear = s->internal->enc_write_ctx ? 0 : 1; /* must be AEAD cipher */ | 793 | goto err; |
772 | } | ||
773 | |||
774 | if (!clear && !S3I(s)->empty_fragment_done) { | ||
775 | /* | ||
776 | * Countermeasure against known-IV weakness in CBC ciphersuites | ||
777 | * (see http://www.openssl.org/~bodo/tls-cbc.txt) | ||
778 | */ | ||
779 | if (S3I(s)->need_empty_fragments && | ||
780 | type == SSL3_RT_APPLICATION_DATA) { | ||
781 | /* extra fragment would be couple of cipher blocks, | ||
782 | * which would be multiple of SSL3_ALIGN_PAYLOAD, so | ||
783 | * if we want to align the real payload, then we can | ||
784 | * just pretent we simply have two headers. */ | ||
785 | align = (size_t)wb->buf + 2 * SSL3_RT_HEADER_LENGTH; | ||
786 | align = (-align) & (SSL3_ALIGN_PAYLOAD - 1); | ||
787 | |||
788 | p = wb->buf + align; | ||
789 | wb->offset = align; | ||
790 | |||
791 | if (!ssl3_create_record(s, p, type, buf, 0)) | ||
792 | goto err; | ||
793 | |||
794 | prefix_len = wr->length; | ||
795 | if (prefix_len > (SSL3_RT_HEADER_LENGTH + | ||
796 | SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD)) { | ||
797 | /* insufficient space */ | ||
798 | SSLerror(s, ERR_R_INTERNAL_ERROR); | ||
799 | goto err; | ||
800 | } | ||
801 | 794 | ||
802 | p = wb->buf + wb->offset + prefix_len; | 795 | prefix_len = wr->length; |
796 | if (prefix_len > (SSL3_RT_HEADER_LENGTH + | ||
797 | SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD)) { | ||
798 | /* insufficient space */ | ||
799 | SSLerror(s, ERR_R_INTERNAL_ERROR); | ||
800 | goto err; | ||
803 | } | 801 | } |
802 | p = wb->buf + wb->offset + prefix_len; | ||
804 | 803 | ||
805 | S3I(s)->empty_fragment_done = 1; | 804 | S3I(s)->empty_fragment_done = 1; |
806 | } | 805 | } |
@@ -808,19 +807,21 @@ do_ssl3_write(SSL *s, int type, const unsigned char *buf, unsigned int len) | |||
808 | if (!ssl3_create_record(s, p, type, buf, len)) | 807 | if (!ssl3_create_record(s, p, type, buf, len)) |
809 | goto err; | 808 | goto err; |
810 | 809 | ||
811 | /* now let's set up wb */ | ||
812 | wb->left = prefix_len + wr->length; | 810 | wb->left = prefix_len + wr->length; |
813 | 811 | ||
814 | /* memorize arguments so that ssl3_write_pending can detect | 812 | /* |
815 | * bad write retries later */ | 813 | * Memorize arguments so that ssl3_write_pending can detect |
814 | * bad write retries later. | ||
815 | */ | ||
816 | S3I(s)->wpend_tot = len; | 816 | S3I(s)->wpend_tot = len; |
817 | S3I(s)->wpend_buf = buf; | 817 | S3I(s)->wpend_buf = buf; |
818 | S3I(s)->wpend_type = type; | 818 | S3I(s)->wpend_type = type; |
819 | S3I(s)->wpend_ret = len; | 819 | S3I(s)->wpend_ret = len; |
820 | 820 | ||
821 | /* we now just need to write the buffer */ | 821 | /* We now just need to write the buffer. */ |
822 | return ssl3_write_pending(s, type, buf, len); | 822 | return ssl3_write_pending(s, type, buf, len); |
823 | err: | 823 | |
824 | err: | ||
824 | return -1; | 825 | return -1; |
825 | } | 826 | } |
826 | 827 | ||