/* do_ssl3_write writes an SSL record of the given type. */ static int do_ssl3_write(SSL *ssl, int type, const uint8_t *buf, unsigned len) { /* If there is still data from the previous record, flush it. */ if (ssl_write_buffer_is_pending(ssl)) { return ssl3_write_pending(ssl, type, buf, len); } /* If we have an alert to send, lets send it */ if (ssl->s3->alert_dispatch) { int ret = ssl->method->dispatch_alert(ssl); if (ret <= 0) { return ret; } /* if it went, fall through and send more stuff */ } if (len > SSL3_RT_MAX_PLAIN_LENGTH) { OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); return -1; } if (len == 0) { return 0; } size_t max_out = len + ssl_max_seal_overhead(ssl); if (max_out < len) { OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW); return -1; } uint8_t *out; size_t ciphertext_len; if (!ssl_write_buffer_init(ssl, &out, max_out) || !tls_seal_record(ssl, out, &ciphertext_len, max_out, type, buf, len)) { return -1; } ssl_write_buffer_set_len(ssl, ciphertext_len); /* memorize arguments so that ssl3_write_pending can detect bad write retries * later */ ssl->s3->wpend_tot = len; ssl->s3->wpend_buf = buf; ssl->s3->wpend_type = type; ssl->s3->wpend_ret = len; /* we now just need to write the buffer */ return ssl3_write_pending(ssl, type, buf, len); }
static int do_dtls1_write(SSL *s, int type, const uint8_t *buf, unsigned int len, enum dtls1_use_epoch_t use_epoch) { /* There should never be a pending write buffer in DTLS. One can't write half * a datagram, so the write buffer is always dropped in * |ssl_write_buffer_flush|. */ assert(!ssl_write_buffer_is_pending(s)); /* If we have an alert to send, lets send it */ if (s->s3->alert_dispatch) { int ret = s->method->ssl_dispatch_alert(s); if (ret <= 0) { return ret; } /* if it went, fall through and send more stuff */ } if (len > SSL3_RT_MAX_PLAIN_LENGTH) { OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); return -1; } if (len == 0) { return 0; } size_t max_out = len + ssl_max_seal_overhead(s); uint8_t *out; size_t ciphertext_len; if (!ssl_write_buffer_init(s, &out, max_out) || !dtls_seal_record(s, out, &ciphertext_len, max_out, type, buf, len, use_epoch)) { ssl_write_buffer_clear(s); return -1; } ssl_write_buffer_set_len(s, ciphertext_len); int ret = ssl_write_buffer_flush(s); if (ret <= 0) { return ret; } return (int)len; }