-/* $OpenBSD: s3_lib.c,v 1.239 2022/10/02 16:36:41 jsing Exp $ */
+/* $OpenBSD: s3_lib.c,v 1.240 2022/11/10 18:06:37 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
ssl3_release_read_buffer(s);
ssl3_release_write_buffer(s);
+ tls_buffer_free(s->s3->alert_fragment);
+ tls_buffer_free(s->s3->handshake_fragment);
+
freezero(s->s3->hs.sigalgs, s->s3->hs.sigalgs_len);
sk_X509_pop_free(s->s3->hs.peer_certs, X509_free);
sk_X509_pop_free(s->s3->hs.peer_certs_no_leaf, X509_free);
sk_X509_pop_free(s->verified_chain, X509_free);
s->verified_chain = NULL;
+ tls_buffer_free(s->s3->alert_fragment);
+ s->s3->alert_fragment = NULL;
+ tls_buffer_free(s->s3->handshake_fragment);
+ s->s3->handshake_fragment = NULL;
+
freezero(s->s3->hs.sigalgs, s->s3->hs.sigalgs_len);
s->s3->hs.sigalgs = NULL;
s->s3->hs.sigalgs_len = 0;
-/* $OpenBSD: ssl_pkt.c,v 1.62 2022/10/21 15:48:14 tb Exp $ */
+/* $OpenBSD: ssl_pkt.c,v 1.63 2022/11/10 18:06:37 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
}
}
+static ssize_t
+ssl3_read_cb(void *buf, size_t n, void *cb_arg)
+{
+ SSL3_RECORD_INTERNAL *rr;
+ SSL *s = cb_arg;
+
+ rr = &s->s3->rrec;
+
+ if (n > rr->length)
+ n = rr->length;
+
+ memcpy(buf, &rr->data[rr->off], n);
+
+ rr->off += n;
+ rr->length -= n;
+
+ return n;
+}
+
+#define SSL3_ALERT_LENGTH 2
+
int
ssl3_read_alert(SSL *s)
{
- SSL3_RECORD_INTERNAL *rr = &s->s3->rrec;
uint8_t alert_level, alert_descr;
+ ssize_t ret;
CBS cbs;
/*
* fragmented across multiple records, hence a full alert must be
* available in the record.
*/
- while (rr->length > 0 &&
- s->s3->alert_fragment_len < sizeof(s->s3->alert_fragment)) {
- s->s3->alert_fragment[s->s3->alert_fragment_len++] =
- rr->data[rr->off++];
- rr->length--;
+ if (s->s3->alert_fragment == NULL) {
+ if ((s->s3->alert_fragment = tls_buffer_new(0)) == NULL)
+ return -1;
+ tls_buffer_set_capacity_limit(s->s3->alert_fragment,
+ SSL3_ALERT_LENGTH);
}
- if (s->s3->alert_fragment_len < sizeof(s->s3->alert_fragment)) {
+ ret = tls_buffer_extend(s->s3->alert_fragment, SSL3_ALERT_LENGTH,
+ ssl3_read_cb, s);
+ if (ret <= 0 && ret != TLS_IO_WANT_POLLIN)
+ return -1;
+ if (ret != SSL3_ALERT_LENGTH) {
if (SSL_is_dtls(s)) {
SSLerror(s, SSL_R_BAD_LENGTH);
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
return 1;
}
- CBS_init(&cbs, s->s3->alert_fragment, sizeof(s->s3->alert_fragment));
+ if (!tls_buffer_data(s->s3->alert_fragment, &cbs))
+ return -1;
ssl_msg_callback_cbs(s, 0, SSL3_RT_ALERT, &cbs);
if (!CBS_get_u8(&cbs, &alert_descr))
return -1;
- s->s3->alert_fragment_len = 0;
+ tls_buffer_free(s->s3->alert_fragment);
+ s->s3->alert_fragment = NULL;
ssl_info_callback(s, SSL_CB_READ_ALERT,
(alert_level << 8) | alert_descr);
static int
ssl3_read_handshake_unexpected(SSL *s)
{
- SSL3_RECORD_INTERNAL *rr = &s->s3->rrec;
uint32_t hs_msg_length;
uint8_t hs_msg_type;
+ ssize_t ssret;
CBS cbs;
int ret;
* header - this may be in the same record or fragmented across multiple
* records.
*/
- while (rr->length > 0 &&
- s->s3->handshake_fragment_len < sizeof(s->s3->handshake_fragment)) {
- s->s3->handshake_fragment[s->s3->handshake_fragment_len++] =
- rr->data[rr->off++];
- rr->length--;
+ if (s->s3->handshake_fragment == NULL) {
+ if ((s->s3->handshake_fragment = tls_buffer_new(0)) == NULL)
+ return -1;
+ tls_buffer_set_capacity_limit(s->s3->handshake_fragment,
+ SSL3_HM_HEADER_LENGTH);
}
-
- if (s->s3->handshake_fragment_len < sizeof(s->s3->handshake_fragment))
+ ssret = tls_buffer_extend(s->s3->handshake_fragment, SSL3_HM_HEADER_LENGTH,
+ ssl3_read_cb, s);
+ if (ssret <= 0 && ssret != TLS_IO_WANT_POLLIN)
+ return -1;
+ if (ssret != SSL3_HM_HEADER_LENGTH)
return 1;
if (s->in_handshake) {
*/
/* Parse handshake message header. */
- CBS_init(&cbs, s->s3->handshake_fragment, s->s3->handshake_fragment_len);
+ if (!tls_buffer_data(s->s3->handshake_fragment, &cbs))
+ return -1;
if (!CBS_get_u8(&cbs, &hs_msg_type))
return -1;
if (!CBS_get_u24(&cbs, &hs_msg_length))
return -1;
}
- ssl_msg_callback(s, 0, SSL3_RT_HANDSHAKE,
- s->s3->handshake_fragment, s->s3->handshake_fragment_len);
+ if (!tls_buffer_data(s->s3->handshake_fragment, &cbs))
+ return -1;
+ ssl_msg_callback_cbs(s, 0, SSL3_RT_HANDSHAKE, &cbs);
- s->s3->handshake_fragment_len = 0;
+ tls_buffer_free(s->s3->handshake_fragment);
+ s->s3->handshake_fragment = NULL;
/*
* It should be impossible to hit this, but keep the safety
return -1;
}
- if (type == SSL3_RT_HANDSHAKE && s->s3->handshake_fragment_len > 0) {
- /* Partially satisfy request from fragment storage. */
- unsigned char *src = s->s3->handshake_fragment;
- unsigned char *dst = buf;
- unsigned int k;
-
- /* peek == 0 */
- n = 0;
- while (len > 0 && s->s3->handshake_fragment_len > 0) {
- *dst++ = *src++;
- len--;
- s->s3->handshake_fragment_len--;
- n++;
+ if (type == SSL3_RT_HANDSHAKE &&
+ s->s3->handshake_fragment != NULL &&
+ tls_buffer_remaining(s->s3->handshake_fragment) > 0) {
+ ssize_t ssn;
+
+ if ((ssn = tls_buffer_read(s->s3->handshake_fragment, buf,
+ len)) <= 0)
+ return -1;
+
+ if (tls_buffer_remaining(s->s3->handshake_fragment) == 0) {
+ tls_buffer_free(s->s3->handshake_fragment);
+ s->s3->handshake_fragment = NULL;
}
- /* move any remaining fragment bytes: */
- for (k = 0; k < s->s3->handshake_fragment_len; k++)
- s->s3->handshake_fragment[k] = *src++;
- return n;
+
+ return (int)ssn;
}
if (SSL_in_init(s) && !s->in_handshake) {