* https://www.openssl.org/source/license.html
*/
-#include <openssl/ssl.h>
+#ifndef OSSL_INTERNAL_RECORDMETHOD_H
+# define OSSL_INTERNAL_RECORDMETHOD_H
+# pragma once
+
+# include <openssl/ssl.h>
/*
* We use the term "record" here to refer to a packet of data. Records are
* refer to both contexts.
*/
-
-/*
- * Types of QUIC record layer;
- *
- * QUIC reuses the TLS handshake for agreeing secrets. An SSL object representing
- * a QUIC connection will have an additional SSL object internally representing
- * the TLS state of the QUIC handshake. This internal TLS is referred to as
- * QUIC-TLS in this file.
- * "Records" output from QUIC-TLS contains standard TLS handshake messages and
- * are *not* encrypted directly but are instead wrapped up in plaintext
- * CRYPTO frames. These CRYPTO frames could be collected together with other
- * QUIC frames into a single QUIC packet. The QUIC record layer will then
- * encrypt the whole packet.
- *
- * So we have:
- * QUIC-TLS record layer: outputs plaintext CRYPTO frames containing TLS
- * handshake messages only.
- * QUIC record layer: outputs encrypted packets which may contain CRYPTO frames
- * or any other type of QUIC frame.
- */
-
/*
* An OSSL_RECORD_METHOD is a protcol specific method which provides the
* functions for reading and writing records for that protocol. Which
typedef struct ossl_record_layer_st OSSL_RECORD_LAYER;
-#define OSSL_RECORD_ROLE_CLIENT 0
-#define OSSL_RECORD_ROLE_SERVER 1
+# define OSSL_RECORD_ROLE_CLIENT 0
+# define OSSL_RECORD_ROLE_SERVER 1
-#define OSSL_RECORD_DIRECTION_READ 0
-#define OSSL_RECORD_DIRECTION_WRITE 1
+# define OSSL_RECORD_DIRECTION_READ 0
+# define OSSL_RECORD_DIRECTION_WRITE 1
/*
* Protection level. For <= TLSv1.2 only "NONE" and "APPLICATION" are used.
*/
-#define OSSL_RECORD_PROTECTION_LEVEL_NONE 0
-#define OSSL_RECORD_PROTECTION_LEVEL_EARLY 1
-#define OSSL_RECORD_PROTECTION_LEVEL_HANDSHAKE 2
-#define OSSL_RECORD_PROTECTION_LEVEL_APPLICATION 3
-
+# define OSSL_RECORD_PROTECTION_LEVEL_NONE 0
+# define OSSL_RECORD_PROTECTION_LEVEL_EARLY 1
+# define OSSL_RECORD_PROTECTION_LEVEL_HANDSHAKE 2
+# define OSSL_RECORD_PROTECTION_LEVEL_APPLICATION 3
-#define OSSL_RECORD_RETURN_SUCCESS 1
-#define OSSL_RECORD_RETURN_RETRY 0
-#define OSSL_RECORD_RETURN_NON_FATAL_ERR -1
-#define OSSL_RECORD_RETURN_FATAL -2
-#define OSSL_RECORD_RETURN_EOF -3
+# define OSSL_RECORD_RETURN_SUCCESS 1
+# define OSSL_RECORD_RETURN_RETRY 0
+# define OSSL_RECORD_RETURN_NON_FATAL_ERR -1
+# define OSSL_RECORD_RETURN_FATAL -2
+# define OSSL_RECORD_RETURN_EOF -3
/*
* Template for creating a record. A record consists of the |type| of data it
- * will contain (e.g. alert, handshake, application data, etc) along with an
- * array of buffers in |bufs| of size |numbufs|. There is a corresponding array
- * of buffer lengths in |buflens|. Concatenating all of the buffer data together
- * would give you the complete plaintext payload to be sent in a single record.
+ * will contain (e.g. alert, handshake, application data, etc) along with a
+ * buffer of payload data in |buf| of length |buflen|.
*/
struct ossl_record_template_st {
int type;
- void **bufs;
- size_t *buflens;
- size_t numbufs;
+ unsigned int version;
+ const unsigned char *buf;
+ size_t buflen;
};
typedef struct ossl_record_template_st OSSL_RECORD_TEMPLATE;
* force at any one time (one for reading and one for writing). In some
* protocols more than 2 might be used (e.g. in DTLS for retransmitting
* messages from an earlier epoch).
+ *
+ * The created OSSL_RECORD_LAYER object is stored in *ret on success (or
+ * NULL otherwise). The return value will be one of
+ * OSSL_RECORD_RETURN_SUCCESS, OSSL_RECORD_RETURN_FATAL or
+ * OSSL_RECORD_RETURN_NON_FATAL. A non-fatal return means that creation of
+ * the record layer has failed because it is unsuitable, but an alternative
+ * record layer can be tried instead.
*/
/*
- * TODO: Will have to be something other than SSL_CIPHER if we make this
- * fetchable
+ * If we eventually make this fetchable then we will need to use something
+ * other than EVP_CIPHER. Also mactype would not be a NID, but a string. For
+ * now though, this works.
*/
- OSSL_RECORD_LAYER *(*new_record_layer)(int vers, int role, int direction,
- int level, unsigned char *secret,
- size_t secretlen, SSL_CIPHER *c,
- BIO *transport, BIO_ADDR *local,
- BIO_ADDR *peer,
- const OSSL_PARAM *settings,
- const OSSL_PARAM *options);
- void (*free)(OSSL_RECORD_LAYER *rl);
+ int (*new_record_layer)(OSSL_LIB_CTX *libctx,
+ const char *propq, int vers,
+ int role, int direction,
+ int level,
+ uint16_t epoch,
+ unsigned char *key,
+ size_t keylen,
+ unsigned char *iv,
+ size_t ivlen,
+ unsigned char *mackey,
+ size_t mackeylen,
+ const EVP_CIPHER *ciph,
+ size_t taglen,
+ int mactype,
+ const EVP_MD *md,
+ COMP_METHOD *comp,
+ BIO *prev,
+ BIO *transport,
+ BIO *next,
+ BIO_ADDR *local,
+ BIO_ADDR *peer,
+ const OSSL_PARAM *settings,
+ const OSSL_PARAM *options,
+ const OSSL_DISPATCH *fns,
+ void *cbarg,
+ OSSL_RECORD_LAYER **ret);
+ int (*free)(OSSL_RECORD_LAYER *rl);
int (*reset)(OSSL_RECORD_LAYER *rl); /* Is this needed? */
/* Returns 1 if we have unprocessed data buffered or 0 otherwise */
int (*unprocessed_read_pending)(OSSL_RECORD_LAYER *rl);
+
/*
* Returns 1 if we have processed data buffered that can be read or 0 otherwise
* - not necessarily app data
*/
size_t (*app_data_pending)(OSSL_RECORD_LAYER *rl);
- int (*write_pending)(OSSL_RECORD_LAYER *rl);
-
-
- /*
- * Find out the maximum amount of plaintext data that the record layer is
- * prepared to write in a single record. When calling write_records it is
- * the caller's responsibility to ensure that no record template exceeds
- * this maximum when calling write_records.
- */
- size_t (*get_max_record_len)(OSSL_RECORD_LAYER *rl);
-
/*
* Find out the maximum number of records that the record layer is prepared
* to process in a single call to write_records. It is the caller's
* responsibility to ensure that no call to write_records exceeds this
- * number of records.
+ * number of records. |type| is the type of the records that the caller
+ * wants to write, and |len| is the total amount of data that it wants
+ * to send. |maxfrag| is the maximum allowed fragment size based on user
+ * configuration, or TLS parameter negotiation. |*preffrag| contains on
+ * entry the default fragment size that will actually be used based on user
+ * configuration. This will always be less than or equal to |maxfrag|. On
+ * exit the record layer may update this to an alternative fragment size to
+ * be used. This must always be less than or equal to |maxfrag|.
*/
- size_t (*get_max_records)(OSSL_RECORD_LAYER *rl);
+ size_t (*get_max_records)(OSSL_RECORD_LAYER *rl, int type, size_t len,
+ size_t maxfrag, size_t *preffrag);
/*
* Write |numtempl| records from the array of record templates pointed to
* by |templates|. Each record should be no longer than the value returned
* by get_max_record_len(), and there should be no more records than the
* value returned by get_max_records().
- * |allowance| is the maximum amount of "on-the-wire" data that is allowed
- * to be sent at the moment (including all QUIC headers, but excluding any
- * UDP/IP headers). After a successful or retry return |*sent| will
- * be updated with the amount of data that has been sent so far. In the case
- * of a retry this could be 0.
* Where possible the caller will attempt to ensure that all records are the
* same length, except the last record. This may not always be possible so
* the record method implementation should not rely on this being the case.
* 0 on retry
* -1 on failure
*/
- int (*write_records)(OSSL_RECORD_LAYER *rl, OSSL_RECORD_TEMPLATE **templates,
- size_t numtempl, size_t allowance, size_t *sent);
+ int (*write_records)(OSSL_RECORD_LAYER *rl, OSSL_RECORD_TEMPLATE *templates,
+ size_t numtempl);
/*
* Retry a previous call to write_records. The caller should continue to
* call this until the function returns with success or failure. After
- * each retry more of the data may have been incrementally sent. |allowance|
- * is the amount of "on-the-wire" data that is allowed to be sent at the
- * moment. After a successful or retry return |*sent| will
- * be updated with the amount of data that has been sent by this call to
- * retry_write_records().
+ * each retry more of the data may have been incrementally sent.
* Returns:
* 1 on success
* 0 on retry
* -1 on failure
*/
- int (*retry_write_records)(OSSL_RECORD_LAYER *rl, size_t allowance,
- size_t *sent);
+ int (*retry_write_records)(OSSL_RECORD_LAYER *rl);
/*
* Read a record and return the record layer version and record type in
*/
int (*read_record)(OSSL_RECORD_LAYER *rl, void **rechandle, int *rversion,
int *type, unsigned char **data, size_t *datalen,
- uint16_t *epoch, unsigned char *seq_num,
- /* TODO(RECLAYER): Remove me */ SSL_CONNECTION *s);
+ uint16_t *epoch, unsigned char *seq_num);
/*
* Release a buffer associated with a record previously read with
* read_record. Records are guaranteed to be released in the order that they
*/
int (*set1_bio)(OSSL_RECORD_LAYER *rl, BIO *bio);
+ /* Called when protocol negotiation selects a protocol version to use */
+ int (*set_protocol_version)(OSSL_RECORD_LAYER *rl, int version);
+
+ /*
+ * Whether we are allowed to receive unencrypted alerts, even if we might
+ * otherwise expect encrypted records. Ignored by protocol versions where
+ * this isn't relevant
+ */
+ void (*set_plain_alerts)(OSSL_RECORD_LAYER *rl, int allow);
+
+ /*
+ * Called immediately after creation of the record layer if we are in a
+ * first handshake. Also called at the end of the first handshake
+ */
+ void (*set_first_handshake)(OSSL_RECORD_LAYER *rl, int first);
+
+ /*
+ * Set the maximum number of pipelines that the record layer should process.
+ * The default is 1.
+ */
+ void (*set_max_pipelines)(OSSL_RECORD_LAYER *rl, size_t max_pipelines);
+
+ /*
+ * Called to tell the record layer whether we are currently "in init" or
+ * not. Default at creation of the record layer is "yes".
+ */
+ void (*set_in_init)(OSSL_RECORD_LAYER *rl, int in_init);
+
+ /*
+ * Get a short or long human readable description of the record layer state
+ */
+ void (*get_state)(OSSL_RECORD_LAYER *rl, const char **shortstr,
+ const char **longstr);
+
+ /*
+ * Set new options or modify ones that were originaly specified in the
+ * new_record_layer call.
+ */
+ int (*set_options)(OSSL_RECORD_LAYER *rl, const OSSL_PARAM *options);
+
+ const COMP_METHOD *(*get_compression)(OSSL_RECORD_LAYER *rl);
+
+ /*
+ * Set the maximum fragment length to be used for the record layer. This
+ * will override any previous value supplied for the "max_frag_len"
+ * setting during construction of the record layer.
+ */
+ void (*set_max_frag_len)(OSSL_RECORD_LAYER *rl, size_t max_frag_len);
+
+ /*
+ * The maximum expansion in bytes that the record layer might add while
+ * writing a record
+ */
+ size_t (*get_max_record_overhead)(OSSL_RECORD_LAYER *rl);
+
+ /*
+ * Increment the record sequence number
+ */
+ int (*increment_sequence_ctr)(OSSL_RECORD_LAYER *rl);
+
+ /*
+ * Allocate read or write buffers. Does nothing if already allocated.
+ * Assumes default buffer length and 1 pipeline.
+ */
+ int (*alloc_buffers)(OSSL_RECORD_LAYER *rl);
+
/*
- * TODO(RECLAYER): Remove these. These function pointers are temporary hacks
- * during the record layer refactoring. They need to be removed before the
- * refactor is complete.
+ * Free read or write buffers. Fails if there is pending read or write
+ * data. Buffers are automatically reallocated on next read/write.
*/
- int (*read_n)(OSSL_RECORD_LAYER *rl, size_t n, size_t max, int extend,
- int clearold, size_t *readbytes);
- SSL3_BUFFER *(*get0_rbuf)(OSSL_RECORD_LAYER *rl);
- unsigned char *(*get0_packet)(OSSL_RECORD_LAYER *rl);
- void (*set0_packet)(OSSL_RECORD_LAYER *rl, unsigned char *packet,
- size_t packetlen);
- size_t (*get_packet_length)(OSSL_RECORD_LAYER *rl);
- void (*reset_packet_length)(OSSL_RECORD_LAYER *rl);
+ int (*free_buffers)(OSSL_RECORD_LAYER *rl);
};
/* Standard built-in record methods */
extern const OSSL_RECORD_METHOD ossl_tls_record_method;
-extern const OSSL_RECORD_METHOD ossl_dtls_record_method;
\ No newline at end of file
+# ifndef OPENSSL_NO_KTLS
+extern const OSSL_RECORD_METHOD ossl_ktls_record_method;
+# endif
+extern const OSSL_RECORD_METHOD ossl_dtls_record_method;
+
+#endif /* !defined(OSSL_INTERNAL_RECORDMETHOD_H) */