/* dtls1_get_record reads a new input record. On success, it places it in * |ssl->s3->rrec| and returns one. Otherwise it returns <= 0 on error or if * more data is needed. */ static int dtls1_get_record(SSL *ssl) { again: /* Read a new packet if there is no unconsumed one. */ if (ssl_read_buffer_len(ssl) == 0) { int ret = ssl_read_buffer_extend_to(ssl, 0 /* unused */); if (ret <= 0) { return ret; } } assert(ssl_read_buffer_len(ssl) > 0); /* Ensure the packet is large enough to decrypt in-place. */ if (ssl_read_buffer_len(ssl) < ssl_record_prefix_len(ssl)) { ssl_read_buffer_clear(ssl); goto again; } uint8_t *out = ssl_read_buffer(ssl) + ssl_record_prefix_len(ssl); size_t max_out = ssl_read_buffer_len(ssl) - ssl_record_prefix_len(ssl); uint8_t type, alert; size_t len, consumed; switch (dtls_open_record(ssl, &type, out, &len, &consumed, &alert, max_out, ssl_read_buffer(ssl), ssl_read_buffer_len(ssl))) { case ssl_open_record_success: ssl_read_buffer_consume(ssl, consumed); if (len > 0xffff) { OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW); return -1; } SSL3_RECORD *rr = &ssl->s3->rrec; rr->type = type; rr->length = (uint16_t)len; rr->data = out; return 1; case ssl_open_record_discard: ssl_read_buffer_consume(ssl, consumed); goto again; case ssl_open_record_error: ssl3_send_alert(ssl, SSL3_AL_FATAL, alert); return -1; case ssl_open_record_partial: /* Impossible in DTLS. */ break; } assert(0); OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); return -1; }
/* ssl3_get_record reads a new input record. On success, it places it in * |ssl->s3->rrec| and returns one. Otherwise it returns <= 0 on error or if * more data is needed. */ static int ssl3_get_record(SSL *ssl) { int ret; again: /* Ensure the buffer is large enough to decrypt in-place. */ ret = ssl_read_buffer_extend_to(ssl, ssl_record_prefix_len(ssl)); if (ret <= 0) { return ret; } assert(ssl_read_buffer_len(ssl) >= ssl_record_prefix_len(ssl)); uint8_t *out = ssl_read_buffer(ssl) + ssl_record_prefix_len(ssl); size_t max_out = ssl_read_buffer_len(ssl) - ssl_record_prefix_len(ssl); uint8_t type, alert; size_t len, consumed; switch (tls_open_record(ssl, &type, out, &len, &consumed, &alert, max_out, ssl_read_buffer(ssl), ssl_read_buffer_len(ssl))) { case ssl_open_record_success: ssl_read_buffer_consume(ssl, consumed); if (len > 0xffff) { OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW); return -1; } SSL3_RECORD *rr = &ssl->s3->rrec; rr->type = type; rr->length = (uint16_t)len; rr->off = 0; rr->data = out; return 1; case ssl_open_record_partial: ret = ssl_read_buffer_extend_to(ssl, consumed); if (ret <= 0) { return ret; } goto again; case ssl_open_record_discard: ssl_read_buffer_consume(ssl, consumed); goto again; case ssl_open_record_error: ssl3_send_alert(ssl, SSL3_AL_FATAL, alert); return -1; } assert(0); OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); return -1; }
/* setup_read_buffer initializes the read buffer if not already initialized. It * returns one on success and zero on failure. */ static int setup_read_buffer(SSL *ssl) { SSL3_BUFFER *buf = &ssl->s3->read_buffer; if (buf->buf != NULL) { return 1; } size_t header_len = ssl_record_prefix_len(ssl); size_t cap = SSL3_RT_MAX_ENCRYPTED_LENGTH; if (SSL_IS_DTLS(ssl)) { cap += DTLS1_RT_HEADER_LENGTH; } else { cap += SSL3_RT_HEADER_LENGTH; } return setup_buffer(buf, header_len, cap); }