/* 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; }
/* 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) { again: switch (ssl->s3->recv_shutdown) { case ssl_shutdown_none: break; case ssl_shutdown_fatal_alert: OPENSSL_PUT_ERROR(SSL, SSL_R_PROTOCOL_IS_SHUTDOWN); return -1; case ssl_shutdown_close_notify: return 0; } CBS body; uint8_t type, alert; size_t consumed; enum ssl_open_record_t open_ret = tls_open_record(ssl, &type, &body, &consumed, &alert, ssl_read_buffer(ssl), ssl_read_buffer_len(ssl)); if (open_ret != ssl_open_record_partial) { ssl_read_buffer_consume(ssl, consumed); } switch (open_ret) { case ssl_open_record_partial: { int read_ret = ssl_read_buffer_extend_to(ssl, consumed); if (read_ret <= 0) { return read_ret; } goto again; } case ssl_open_record_success: if (CBS_len(&body) > 0xffff) { OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW); return -1; } SSL3_RECORD *rr = &ssl->s3->rrec; rr->type = type; rr->length = (uint16_t)CBS_len(&body); rr->data = (uint8_t *)CBS_data(&body); return 1; case ssl_open_record_discard: goto again; case ssl_open_record_close_notify: return 0; case ssl_open_record_fatal_alert: return -1; 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; }
/* 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; }