summaryrefslogtreecommitdiff
path: root/src/lib/libssl/ssl_pkt.c
diff options
context:
space:
mode:
authorjsing <>2020-08-09 16:02:58 +0000
committerjsing <>2020-08-09 16:02:58 +0000
commitb3dbcda2404dbe31481fae8d6817cbc0a3362031 (patch)
tree1bce0663b79d08c1bf38e62b09a464cbcc5bd6ce /src/lib/libssl/ssl_pkt.c
parente770512d626b103f809dfdecb1ba758a92b5f57b (diff)
downloadopenbsd-b3dbcda2404dbe31481fae8d6817cbc0a3362031.tar.gz
openbsd-b3dbcda2404dbe31481fae8d6817cbc0a3362031.tar.bz2
openbsd-b3dbcda2404dbe31481fae8d6817cbc0a3362031.zip
Use CBB more correctly when writing SSL3/DTLS records.
Previously we used CBB to build the record headers, but not the entire record. Use CBB_init_fixed() upfront, then build the record header and add space for the record content. However, in order to do this we need to determine the length of the record upfront. This simplifies the code, removes a number of manual bounds checks and makes way for further improvements. ok inoguchi@ tb@
Diffstat (limited to 'src/lib/libssl/ssl_pkt.c')
-rw-r--r--src/lib/libssl/ssl_pkt.c90
1 files changed, 49 insertions, 41 deletions
diff --git a/src/lib/libssl/ssl_pkt.c b/src/lib/libssl/ssl_pkt.c
index 39ce46381d..da059915f2 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.28 2020/08/02 07:33:15 jsing Exp $ */ 1/* $OpenBSD: ssl_pkt.c,v 1.29 2020/08/09 16:02:58 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 *
@@ -617,15 +617,15 @@ ssl3_write_bytes(SSL *s, int type, const void *buf_, int len)
617} 617}
618 618
619static int 619static int
620ssl3_create_record(SSL *s, unsigned char *p, uint16_t version, uint8_t type, 620ssl3_create_record(SSL *s, CBB *cbb, uint16_t version, uint8_t type,
621 const unsigned char *buf, unsigned int len) 621 const unsigned char *buf, unsigned int len)
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 = 0, mac_size = 0; 625 int block_size = 0, eivlen = 0, mac_size = 0;
626 CBB cbb; 626 size_t pad_len, record_len;
627 627 CBB fragment;
628 memset(&cbb, 0, sizeof(cbb)); 628 uint8_t *p;
629 629
630 if (sess != NULL && s->internal->enc_write_ctx != NULL && 630 if (sess != NULL && s->internal->enc_write_ctx != NULL &&
631 EVP_MD_CTX_md(s->internal->write_hash) != NULL) { 631 EVP_MD_CTX_md(s->internal->write_hash) != NULL) {
@@ -633,17 +633,6 @@ ssl3_create_record(SSL *s, unsigned char *p, uint16_t version, uint8_t type,
633 goto err; 633 goto err;
634 } 634 }
635 635
636 if (!CBB_init_fixed(&cbb, p, SSL3_RT_HEADER_LENGTH))
637 goto err;
638
639 /* Write the header. */
640 if (!CBB_add_u8(&cbb, type))
641 goto err;
642 if (!CBB_add_u16(&cbb, version))
643 goto err;
644
645 p += SSL3_RT_HEADER_LENGTH;
646
647 /* Explicit IV length. */ 636 /* Explicit IV length. */
648 if (s->internal->enc_write_ctx && SSL_USE_EXPLICIT_IV(s)) { 637 if (s->internal->enc_write_ctx && SSL_USE_EXPLICIT_IV(s)) {
649 int mode = EVP_CIPHER_CTX_mode(s->internal->enc_write_ctx); 638 int mode = EVP_CIPHER_CTX_mode(s->internal->enc_write_ctx);
@@ -657,6 +646,31 @@ ssl3_create_record(SSL *s, unsigned char *p, uint16_t version, uint8_t type,
657 eivlen = s->internal->aead_write_ctx->variable_nonce_len; 646 eivlen = s->internal->aead_write_ctx->variable_nonce_len;
658 } 647 }
659 648
649 /* Determine length of record fragment. */
650 record_len = eivlen + len + mac_size;
651 if (s->internal->enc_write_ctx != NULL) {
652 block_size = EVP_CIPHER_CTX_block_size(s->internal->enc_write_ctx);
653 if (block_size <= 0 || block_size > EVP_MAX_BLOCK_LENGTH)
654 goto err;
655 if (block_size > 1) {
656 pad_len = block_size - (record_len % block_size);
657 record_len += pad_len;
658 }
659 } else if (s->internal->aead_write_ctx != NULL) {
660 record_len += s->internal->aead_write_ctx->tag_len;
661 }
662
663 /* Write the header. */
664 if (!CBB_add_u8(cbb, type))
665 goto err;
666 if (!CBB_add_u16(cbb, version))
667 goto err;
668 if (!CBB_add_u16_length_prefixed(cbb, &fragment))
669 goto err;
670 if (!CBB_add_space(&fragment, &p, record_len))
671 goto err;
672
673 /* Set up the record. */
660 wr->type = type; 674 wr->type = type;
661 wr->data = p + eivlen; 675 wr->data = p + eivlen;
662 wr->length = (int)len; 676 wr->length = (int)len;
@@ -677,10 +691,10 @@ ssl3_create_record(SSL *s, unsigned char *p, uint16_t version, uint8_t type,
677 if (tls1_enc(s, 1) != 1) 691 if (tls1_enc(s, 1) != 1)
678 goto err; 692 goto err;
679 693
680 /* record length after mac and block padding */ 694 if (wr->length != record_len)
681 if (!CBB_add_u16(&cbb, wr->length))
682 goto err; 695 goto err;
683 if (!CBB_finish(&cbb, NULL, NULL)) 696
697 if (!CBB_flush(cbb))
684 goto err; 698 goto err;
685 699
686 /* 700 /*
@@ -693,24 +707,22 @@ ssl3_create_record(SSL *s, unsigned char *p, uint16_t version, uint8_t type,
693 return 1; 707 return 1;
694 708
695 err: 709 err:
696 CBB_cleanup(&cbb);
697
698 return 0; 710 return 0;
699} 711}
700 712
701static int 713static int
702do_ssl3_write(SSL *s, int type, const unsigned char *buf, unsigned int len) 714do_ssl3_write(SSL *s, int type, const unsigned char *buf, unsigned int len)
703{ 715{
704 SSL3_RECORD_INTERNAL *wr = &(S3I(s)->wrec);
705 SSL3_BUFFER_INTERNAL *wb = &(S3I(s)->wbuf); 716 SSL3_BUFFER_INTERNAL *wb = &(S3I(s)->wbuf);
706 SSL_SESSION *sess = s->session; 717 SSL_SESSION *sess = s->session;
707 unsigned char *p;
708 int need_empty_fragment = 0; 718 int need_empty_fragment = 0;
709 int prefix_len = 0; 719 size_t align, out_len;
710 uint16_t version; 720 uint16_t version;
711 size_t align; 721 CBB cbb;
712 int ret; 722 int ret;
713 723
724 memset(&cbb, 0, sizeof(cbb));
725
714 if (wb->buf == NULL) 726 if (wb->buf == NULL)
715 if (!ssl3_setup_write_buffer(s)) 727 if (!ssl3_setup_write_buffer(s))
716 return -1; 728 return -1;
@@ -768,30 +780,24 @@ do_ssl3_write(SSL *s, int type, const unsigned char *buf, unsigned int len)
768 if (need_empty_fragment) 780 if (need_empty_fragment)
769 align += SSL3_RT_HEADER_LENGTH; 781 align += SSL3_RT_HEADER_LENGTH;
770 align = (-align) & (SSL3_ALIGN_PAYLOAD - 1); 782 align = (-align) & (SSL3_ALIGN_PAYLOAD - 1);
771
772 p = wb->buf + align;
773 wb->offset = align; 783 wb->offset = align;
774 784
775 if (need_empty_fragment) { 785 if (!CBB_init_fixed(&cbb, wb->buf + align, wb->len - align))
776 if (!ssl3_create_record(s, p, version, type, buf, 0)) 786 goto err;
777 goto err;
778 787
779 prefix_len = wr->length; 788 if (need_empty_fragment) {
780 if (prefix_len > (SSL3_RT_HEADER_LENGTH + 789 if (!ssl3_create_record(s, &cbb, version, type, buf, 0))
781 SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD)) {
782 /* insufficient space */
783 SSLerror(s, ERR_R_INTERNAL_ERROR);
784 goto err; 790 goto err;
785 }
786 p = wb->buf + wb->offset + prefix_len;
787
788 S3I(s)->empty_fragment_done = 1; 791 S3I(s)->empty_fragment_done = 1;
789 } 792 }
790 793
791 if (!ssl3_create_record(s, p, version, type, buf, len)) 794 if (!ssl3_create_record(s, &cbb, version, type, buf, len))
792 goto err; 795 goto err;
793 796
794 wb->left = prefix_len + wr->length; 797 if (!CBB_finish(&cbb, NULL, &out_len))
798 goto err;
799
800 wb->left = out_len;
795 801
796 /* 802 /*
797 * Memorize arguments so that ssl3_write_pending can detect 803 * Memorize arguments so that ssl3_write_pending can detect
@@ -806,6 +812,8 @@ do_ssl3_write(SSL *s, int type, const unsigned char *buf, unsigned int len)
806 return ssl3_write_pending(s, type, buf, len); 812 return ssl3_write_pending(s, type, buf, len);
807 813
808 err: 814 err:
815 CBB_cleanup(&cbb);
816
809 return -1; 817 return -1;
810} 818}
811 819