]>
Commit | Line | Data |
---|---|---|
14b54475 MC |
1 | Design Problem: Abstract Record Layer |
2 | ===================================== | |
3 | ||
48cc4e0c MC |
4 | This document covers the design of an abstract record layer for use in (D)TLS. |
5 | The QUIC record layer is handled separately. | |
14b54475 MC |
6 | |
7 | A record within this document refers to a packet of data. It will typically | |
48cc4e0c | 8 | contain some header data and some payload data, and will often be |
14b54475 | 9 | cryptographically protected. A record may or may not have a one-to-one |
48cc4e0c MC |
10 | correspondence with network packets, depending on the implementation details of |
11 | an individual record layer. | |
14b54475 | 12 | |
48cc4e0c | 13 | The term record comes directly from the TLS and DTLS specifications. |
14b54475 | 14 | |
48cc4e0c MC |
15 | Libssl supports a number of different types of record layer, and record layer |
16 | variants: | |
14b54475 MC |
17 | |
18 | - Standard TLS record layer | |
19 | - Standard DTLS record layer | |
20 | - Kernel TLS record layer | |
21 | ||
22 | Within the TLS record layer there are options to handle "multiblock" and | |
23 | "pipelining" which are different approaches for supporting the reading or | |
48cc4e0c MC |
24 | writing of multiple records at the same time. All record layer variants also |
25 | have to be able to handle different protocol versions. | |
14b54475 | 26 | |
48cc4e0c MC |
27 | These different record layer implementations, variants and protocol versions |
28 | have each been added at different times and over many years. The result is that | |
29 | each took slightly different approaches for achieving the goals that were | |
30 | appropriate at the time and the integration points where they were added were | |
31 | spread throughout the code. | |
14b54475 | 32 | |
48cc4e0c MC |
33 | The introduction of QUIC support will see the implementation of a new record |
34 | layer, i.e. the QUIC-TLS record layer. This refers to the "inner" TLS | |
35 | implementation used by QUIC. Records here will be in the form of QUIC CRYPTO | |
36 | frames. | |
14b54475 MC |
37 | |
38 | Requirements | |
39 | ------------ | |
40 | ||
41 | The technical requirements | |
42 | [document](https://github.com/openssl/openssl/blob/master/doc/designs/quic-design/quic-requirements.md) | |
43 | lists these requirements that are relevant to the record layer: | |
44 | ||
45 | * The current libssl record layer includes support for TLS, DTLS and KTLS. QUIC | |
46 | will introduce another variant and there may be more over time. The OMC | |
47 | requires a pluggable record layer interface to be implemented to enable this | |
48 | to be less intrusive, more maintainable, and to harmonize the existing record | |
49 | layer interactions between TLS, DTLS, KTLS and the planned QUIC protocols. The | |
50 | pluggable record layer interface will be internal only for MVP and be public | |
51 | in a future release. | |
52 | ||
53 | * The minimum viable product (MVP) for the next release is a pluggable record | |
54 | layer interface and a single stream QUIC client in the form of s_client that | |
55 | does not require significant API changes. In the MVP, interoperability should | |
56 | be prioritized over strict standards compliance. | |
57 | ||
58 | * Once we have a fully functional QUIC implementation (in a subsequent release), | |
59 | it should be possible for external libraries to be able to use the pluggable | |
60 | record layer interface and it should offer a stable ABI (via a provider). | |
61 | ||
14b54475 MC |
62 | The MVP requirements are: |
63 | ||
64 | * a pluggable record layer (not public for MVP) | |
65 | ||
48cc4e0c MC |
66 | Candidate Solutions that were considered |
67 | ---------------------------------------- | |
68 | ||
69 | This section outlines two different solution approaches that were considered for | |
70 | the abstract record layer | |
71 | ||
72 | ### Use a METHOD based approach | |
14b54475 MC |
73 | |
74 | A METHOD based approach is simply a structure containing function pointers. It | |
75 | is a common pattern in the OpenSSL codebase. Different strategies for | |
76 | implementing a METHOD can be employed, but these differences are hidden from | |
77 | the caller of the METHOD. | |
78 | ||
79 | In this solution we would seek to implement a different METHOD for each of the | |
80 | types of record layer that we support, i.e. there would be one for the standard | |
48cc4e0c MC |
81 | TLS record layer, one for the standard DTLS record layer, one for kernel TLS and |
82 | one for QUIC-TLS. | |
14b54475 MC |
83 | |
84 | In the MVP the METHOD approach would be private. However, once it has | |
85 | stabilised, it would be straight forward to supply public functions to enable | |
86 | end user applications to construct their own METHODs. | |
87 | ||
88 | This option is simpler to implement than the alternative of having a provider | |
89 | based approach. However it could be used as a "stepping stone" for that, i.e. | |
90 | the MVP could implement a METHOD based approach, and subsequent releases could | |
91 | convert the METHODs into fully fetchable algorithms. | |
92 | ||
93 | Pros: | |
48cc4e0c | 94 | |
14b54475 MC |
95 | * Simple approach that has been used historically in OpenSSL |
96 | * Could be used as the basis for the final public solution | |
97 | * Could also be used as the basis for a fetchable solution in a subsequent | |
98 | release | |
99 | * If this option is later converted to a fetchable solution then much of the | |
100 | effort involved in making the record layer fetchable can be deferred to a | |
101 | later release | |
102 | ||
103 | Cons: | |
48cc4e0c | 104 | |
14b54475 MC |
105 | * Not consistent with the provider based approach we used for extensibility in |
106 | 3.0 | |
107 | * If this option is implemented and later converted to a fetchable solution then | |
108 | some rework might be required | |
109 | ||
48cc4e0c | 110 | ### Use a provider based approach |
14b54475 MC |
111 | |
112 | This approach is very similar to the alternative METHOD based approach. The | |
113 | main difference is that the record layer implementations would be held in | |
114 | providers and "fetched" in much the same way that cryptographic algorithms are | |
115 | fetched in OpenSSL 3.0. | |
116 | ||
117 | This approach is more consistent with the approach adopted for extensibility in | |
118 | 3.0. METHODS are being deprecated with providers being used extensively. | |
119 | ||
120 | Complex objects (e.g. an `SSL` object) cannot be passed across the | |
121 | libssl/provider boundary. This imposes some restrictions on the design of the | |
122 | functions that can be implemented. Additionally implementing the infrastructure | |
123 | for a new fetchable operation is more involved than a METHOD based approach. | |
124 | ||
125 | Pros: | |
48cc4e0c | 126 | |
14b54475 MC |
127 | * Consistent with the extensibility solution used in 3.0 |
128 | * If this option is implemented immediately in the MVP then it would avoid later | |
129 | rework if adopted in a subsequent release | |
130 | ||
131 | Cons: | |
48cc4e0c | 132 | |
14b54475 MC |
133 | * More complicated to implement than the simple METHOD based approach |
134 | * Cannot pass complex objects across the provider boundary | |
135 | ||
48cc4e0c MC |
136 | ### Selected solution |
137 | ||
138 | The METHOD based approach has been selected for MVP, with the expectation that | |
139 | subsequent releases will convert it to a full provider based solution accessible | |
140 | to third party applications. | |
14b54475 | 141 | |
48cc4e0c MC |
142 | Solution Description: The METHOD based approach |
143 | ----------------------------------------------- | |
14b54475 | 144 | |
48cc4e0c MC |
145 | This section focuses on the selected approach of using METHODs and further |
146 | elaborates on how the design works. | |
14b54475 | 147 | |
48cc4e0c MC |
148 | A proposed internal record method API is given in |
149 | [Appendix A](#appendix-a-the-internal-record-method-api). | |
14b54475 MC |
150 | |
151 | An `OSSL_RECORD_METHOD` represents the implementation of a particular type of | |
152 | record layer. It contains a set of function pointers to represent the various | |
153 | actions that can be performed by a record layer. | |
154 | ||
155 | An `OSSL_RECORD_LAYER` object represents a specific instantiation of a | |
156 | particular `OSSL_RECORD_METHOD`. It contains the state used by that | |
157 | `OSSL_RECORD_METHOD` for a specific connection (i.e. `SSL` object). Any `SSL` | |
158 | object will have at least 2 `OSSL_RECORD_LAYER` objects associated with it - one | |
159 | for reading and one for writing. In some cases there may be more than 2 - for | |
160 | example in DTLS it may be necessary to retransmit records from a previous epoch. | |
161 | There will be different `OSSL_RECORD_LAYER` objects for different protection | |
162 | levels or epochs. It may be that different `OSSL_RECORD_METHOD`s are used for | |
163 | different protection levels. For example a connection might start using the | |
164 | standard TLS record layer during the handshake, and later transition to using | |
165 | the kernel TLS record layer once the handshake is complete. | |
166 | ||
167 | A new `OSSL_RECORD_LAYER` is created by calling the `new` function of the | |
168 | associated `OSSL_RECORD_METHOD`, and freed by calling the `free` function. The | |
48cc4e0c MC |
169 | parameters to the `new` function also supply all of the cryptographic state |
170 | (e.g. keys, ivs, symmetric encryption algorithms, hash algorithm etc) used by | |
171 | the record layer. The internal structure details of an `OSSL_RECORD_LAYER` are | |
172 | entirely hidden to the rest of libssl and can be specific to the given | |
173 | `OSSL_RECORD_METHOD`. In practice the standard internal TLS, DTLS and KTLS | |
174 | `OSSL_RECORD_METHOD`s all use a common `OSSL_RECORD_LAYER` structure. However | |
175 | the QUIC-TLS implementation is likely to use a different structure layout. | |
176 | ||
177 | All of the header and payload data for a single record will be represented by an | |
178 | `OSSL_RECORD_TEMPLATE` structure when writing. Libssl will construct a set of | |
179 | templates for records to be written out and pass them to the "write" record | |
180 | layer. In most cases only a single record is ever written out at one time, | |
181 | however there are some cases (such as when using the "pipelining" or | |
182 | "multibuffer" optimisations) that multiple records can be written in one go. | |
183 | ||
184 | It is the record layer's responsibility to know whether it can support multiple | |
185 | records in one go or not. It is libssl's responsibility to split the payload | |
186 | data into `OSSL_RECORD_TEMPLATE` objects. Libssl will call the record layer's | |
187 | `get_max_records()` function to determine how many records a given payload | |
188 | should be split into. If that value is more than one, then libssl will construct | |
189 | (up to) that number of `OSSL_RECORD_TEMPLATE`s and pass the whole set to the | |
190 | record layer's `write_records()` function. | |
14b54475 MC |
191 | |
192 | The implementation of the `write_records` function must construct the | |
193 | appropriate number of records, apply protection to them as required and then | |
48cc4e0c MC |
194 | write them out to the underlying transport layer BIO. In the event that not |
195 | all the data can be transmitted at the current time (e.g. because the underlying | |
196 | transport has indicated a retry), then the `write_records` function will return | |
197 | a "retry" response. It is permissible for the data to be partially sent, but | |
198 | this is still considered a "retry" until all of the data is sent. | |
14b54475 MC |
199 | |
200 | On a success or retry response libssl may free its buffers immediately. The | |
201 | `OSSL_RECORD_LAYER` object will have to buffer any untransmitted data until it | |
48cc4e0c | 202 | is eventually sent. |
14b54475 MC |
203 | |
204 | If a "retry" occurs, then libssl will subsequently call `retry_write_records` | |
205 | and continue to do so until a success return value is received. Libssl will | |
206 | never call `write_records` a second time until a previous call to | |
207 | `write_records` or `retry_write_records` has indicated success. | |
208 | ||
209 | Libssl will read records by calling the `read_record` function. The | |
210 | `OSSL_RECORD_LAYER` may read multiple records in one go and buffer them, but the | |
211 | `read_record` function only ever returns one record at a time. The | |
212 | `OSSL_RECORD_LAYER` object owns the buffers for the record that has been read | |
213 | and supplies a pointer into that buffer back to libssl for the payload data, as | |
214 | well as other information about the record such as its length and the type of | |
215 | data contained in it. Each record has an associated opaque handle `rechandle`. | |
216 | The record data must remain buffered by the `OSSL_RECORD_LAYER` until it has | |
217 | been released via a call to `release_record()`. | |
218 | ||
48cc4e0c MC |
219 | A record layer implementation supplies various functions to enable libssl to |
220 | query the current state. In particular: | |
14b54475 | 221 | |
48cc4e0c MC |
222 | `unprocessed_read_pending()`: to query whether there is data buffered that has |
223 | already been read from the underlying BIO, but not yet processed. | |
14b54475 | 224 | |
48cc4e0c MC |
225 | `processed_read_pending()`: to query whether there is data buffered that has |
226 | been read from the underlying BIO and has been processed. The data is not | |
227 | necessarily application data. | |
228 | ||
229 | `app_data_pending()`: to query the amount of processed application data that is | |
230 | buffered and available for immediate read. | |
231 | ||
232 | `get_alert_code()`: to query the alert code that should be used in the event | |
233 | that a previous attempt to read or write records failed. | |
234 | ||
235 | `get_state()`: to obtain a printable string to describe the current state of the | |
236 | record layer. | |
237 | ||
238 | `get_compression()`: to obtain information about the compression method | |
239 | currently being used by the record layer. | |
240 | ||
241 | `get_max_record_overhead()`: to obtain the maximum amount of bytes the record | |
242 | layer will add to the payload bytes before transmission. This does not include | |
243 | any expansion that might occur during compression. Currently this is only | |
244 | implemented for DTLS. | |
245 | ||
246 | In addition, libssl will tell the record layer about various events that might | |
247 | occur that are relevant to the record layer's operation: | |
248 | ||
249 | `set1_bio()`: called if the underlying BIO being used by the record layer has | |
250 | been changed. | |
251 | ||
252 | `set_protocol_version()`: called during protocol version negotiation when a | |
253 | specific protocol version has been selected. | |
254 | ||
255 | `set_plain_alerts()`: to indicate that receiving unencrypted alerts is allowed | |
256 | in the current context, even if normally we would expect to receive encrypted | |
257 | data. This is only relevant for TLSv1.3. | |
258 | ||
259 | `set_first_handshake()`: called at the beginning and end of the first handshake | |
260 | for any given (D)TLS connection. | |
14b54475 | 261 | |
48cc4e0c MC |
262 | `set_max_pipelines()`: called to configure the maximum number of pipelines of |
263 | data that the record layer should process in one go. By default this is 1. | |
14b54475 | 264 | |
48cc4e0c MC |
265 | `set_in_init()`: called by libssl to tell the record layer whether we are |
266 | currently `in_init` or not. Defaults to "true". | |
267 | ||
268 | `set_options()`: called by libssl in the event that the current set of options | |
269 | to use has been updated. | |
270 | ||
271 | `set_max_frag_len()`: called by libssl to set the maximum allowed fragment | |
272 | length that is in force at the moment. This might be the result of user | |
273 | configuration, or it may be negotiated during the handshake. | |
274 | ||
275 | `increment_sequence_ctr()`: force the record layer to increment its sequence | |
276 | counter. In most cases the record layer will entirely manage its own sequence | |
277 | counters. However in the DTLSv1_listen() corner case, libssl needs to initialise | |
278 | the record layer with an incremented sequence counter. | |
279 | ||
280 | `alloc_buffers()`: called by libssl to request that the record layer allocate | |
281 | its buffers. This is a hint only and the record layer is expected to manage its | |
282 | own buffer allocation and freeing. | |
283 | ||
284 | `free_buffers()`: called by libssl to request that the record layer free its | |
285 | buffers. This is a hint only and the record layer is expected to manage its own | |
286 | buffer allocation and freeing. | |
287 | ||
288 | Appendix A: The internal record method API | |
289 | ------------------------------------------ | |
290 | ||
291 | The internal recordmethod.h header file for the record method API: | |
292 | ||
293 | ```` C | |
14b54475 MC |
294 | /* |
295 | * We use the term "record" here to refer to a packet of data. Records are | |
296 | * typically protected via a cipher and MAC, or an AEAD cipher (although not | |
297 | * always). This usage of the term record is consistent with the TLS concept. | |
298 | * In QUIC the term "record" is not used but it is analogous to the QUIC term | |
299 | * "packet". The interface in this file applies to all protocols that protect | |
300 | * records/packets of data, i.e. (D)TLS and QUIC. The term record is used to | |
301 | * refer to both contexts. | |
302 | */ | |
303 | ||
14b54475 | 304 | /* |
eb4129e1 | 305 | * An OSSL_RECORD_METHOD is a protocol specific method which provides the |
14b54475 MC |
306 | * functions for reading and writing records for that protocol. Which |
307 | * OSSL_RECORD_METHOD to use for a given protocol is defined by the SSL_METHOD. | |
308 | */ | |
309 | typedef struct ossl_record_method_st OSSL_RECORD_METHOD; | |
310 | ||
311 | /* | |
312 | * An OSSL_RECORD_LAYER is just an externally defined opaque pointer created by | |
313 | * the method | |
314 | */ | |
315 | typedef struct ossl_record_layer_st OSSL_RECORD_LAYER; | |
316 | ||
317 | ||
48cc4e0c MC |
318 | # define OSSL_RECORD_ROLE_CLIENT 0 |
319 | # define OSSL_RECORD_ROLE_SERVER 1 | |
14b54475 | 320 | |
48cc4e0c MC |
321 | # define OSSL_RECORD_DIRECTION_READ 0 |
322 | # define OSSL_RECORD_DIRECTION_WRITE 1 | |
14b54475 MC |
323 | |
324 | /* | |
325 | * Protection level. For <= TLSv1.2 only "NONE" and "APPLICATION" are used. | |
326 | */ | |
48cc4e0c MC |
327 | # define OSSL_RECORD_PROTECTION_LEVEL_NONE 0 |
328 | # define OSSL_RECORD_PROTECTION_LEVEL_EARLY 1 | |
329 | # define OSSL_RECORD_PROTECTION_LEVEL_HANDSHAKE 2 | |
330 | # define OSSL_RECORD_PROTECTION_LEVEL_APPLICATION 3 | |
14b54475 | 331 | |
48cc4e0c MC |
332 | # define OSSL_RECORD_RETURN_SUCCESS 1 |
333 | # define OSSL_RECORD_RETURN_RETRY 0 | |
334 | # define OSSL_RECORD_RETURN_NON_FATAL_ERR -1 | |
335 | # define OSSL_RECORD_RETURN_FATAL -2 | |
336 | # define OSSL_RECORD_RETURN_EOF -3 | |
14b54475 MC |
337 | |
338 | /* | |
339 | * Template for creating a record. A record consists of the |type| of data it | |
48cc4e0c MC |
340 | * will contain (e.g. alert, handshake, application data, etc) along with a |
341 | * buffer of payload data in |buf| of length |buflen|. | |
14b54475 MC |
342 | */ |
343 | struct ossl_record_template_st { | |
344 | int type; | |
48cc4e0c MC |
345 | unsigned int version; |
346 | const unsigned char *buf; | |
347 | size_t buflen; | |
14b54475 MC |
348 | }; |
349 | ||
350 | typedef struct ossl_record_template_st OSSL_RECORD_TEMPLATE; | |
351 | ||
352 | /* | |
353 | * Rather than a "method" approach, we could make this fetchable - Should we? | |
354 | * There could be some complexity in finding suitable record layer implementations | |
355 | * e.g. we need to find one that matches the negotiated protocol, cipher, | |
356 | * extensions, etc. The selection_cb approach given above doesn't work so well | |
357 | * if unknown third party providers with OSSL_RECORD_METHOD implementations are | |
358 | * loaded. | |
359 | */ | |
360 | ||
361 | /* | |
362 | * If this becomes public API then we will need functions to create and | |
363 | * free an OSSL_RECORD_METHOD, as well as functions to get/set the various | |
364 | * function pointers....unless we make it fetchable. | |
365 | */ | |
366 | struct ossl_record_method_st { | |
367 | /* | |
368 | * Create a new OSSL_RECORD_LAYER object for handling the protocol version | |
369 | * set by |vers|. |role| is 0 for client and 1 for server. |direction| | |
370 | * indicates either read or write. |level| is the protection level as | |
371 | * described above. |settings| are mandatory settings that will cause the | |
372 | * new() call to fail if they are not understood (for example to require | |
373 | * Encrypt-Then-Mac support). |options| are optional settings that will not | |
374 | * cause the new() call to fail if they are not understood (for example | |
375 | * whether to use "read ahead" or not). | |
376 | * | |
377 | * The BIO in |transport| is the BIO for the underlying transport layer. | |
378 | * Where the direction is "read", then this BIO will only ever be used for | |
379 | * reading data. Where the direction is "write", then this BIO will only | |
380 | * every be used for writing data. | |
381 | * | |
382 | * An SSL object will always have at least 2 OSSL_RECORD_LAYER objects in | |
383 | * force at any one time (one for reading and one for writing). In some | |
384 | * protocols more than 2 might be used (e.g. in DTLS for retransmitting | |
385 | * messages from an earlier epoch). | |
48cc4e0c MC |
386 | * |
387 | * The created OSSL_RECORD_LAYER object is stored in *ret on success (or | |
388 | * NULL otherwise). The return value will be one of | |
389 | * OSSL_RECORD_RETURN_SUCCESS, OSSL_RECORD_RETURN_FATAL or | |
390 | * OSSL_RECORD_RETURN_NON_FATAL. A non-fatal return means that creation of | |
391 | * the record layer has failed because it is unsuitable, but an alternative | |
392 | * record layer can be tried instead. | |
14b54475 MC |
393 | */ |
394 | ||
395 | /* | |
48cc4e0c MC |
396 | * If we eventually make this fetchable then we will need to use something |
397 | * other than EVP_CIPHER. Also mactype would not be a NID, but a string. For | |
398 | * now though, this works. | |
14b54475 | 399 | */ |
48cc4e0c MC |
400 | int (*new_record_layer)(OSSL_LIB_CTX *libctx, |
401 | const char *propq, int vers, | |
402 | int role, int direction, | |
403 | int level, | |
404 | uint16_t epoch, | |
405 | unsigned char *key, | |
406 | size_t keylen, | |
407 | unsigned char *iv, | |
408 | size_t ivlen, | |
409 | unsigned char *mackey, | |
410 | size_t mackeylen, | |
411 | const EVP_CIPHER *ciph, | |
412 | size_t taglen, | |
413 | int mactype, | |
414 | const EVP_MD *md, | |
415 | COMP_METHOD *comp, | |
416 | BIO *prev, | |
417 | BIO *transport, | |
418 | BIO *next, | |
419 | BIO_ADDR *local, | |
420 | BIO_ADDR *peer, | |
421 | const OSSL_PARAM *settings, | |
422 | const OSSL_PARAM *options, | |
423 | const OSSL_DISPATCH *fns, | |
424 | void *cbarg, | |
425 | OSSL_RECORD_LAYER **ret); | |
426 | int (*free)(OSSL_RECORD_LAYER *rl); | |
427 | ||
428 | int (*reset)(OSSL_RECORD_LAYER *rl); /* Is this needed? */ | |
14b54475 MC |
429 | |
430 | /* Returns 1 if we have unprocessed data buffered or 0 otherwise */ | |
48cc4e0c MC |
431 | int (*unprocessed_read_pending)(OSSL_RECORD_LAYER *rl); |
432 | ||
14b54475 MC |
433 | /* |
434 | * Returns 1 if we have processed data buffered that can be read or 0 otherwise | |
435 | * - not necessarily app data | |
436 | */ | |
48cc4e0c | 437 | int (*processed_read_pending)(OSSL_RECORD_LAYER *rl); |
14b54475 MC |
438 | |
439 | /* | |
eb4129e1 | 440 | * The amount of processed app data that is internally buffered and |
14b54475 MC |
441 | * available to read |
442 | */ | |
48cc4e0c | 443 | size_t (*app_data_pending)(OSSL_RECORD_LAYER *rl); |
14b54475 MC |
444 | |
445 | /* | |
446 | * Find out the maximum number of records that the record layer is prepared | |
447 | * to process in a single call to write_records. It is the caller's | |
448 | * responsibility to ensure that no call to write_records exceeds this | |
48cc4e0c MC |
449 | * number of records. |type| is the type of the records that the caller |
450 | * wants to write, and |len| is the total amount of data that it wants | |
451 | * to send. |maxfrag| is the maximum allowed fragment size based on user | |
452 | * configuration, or TLS parameter negotiation. |*preffrag| contains on | |
453 | * entry the default fragment size that will actually be used based on user | |
454 | * configuration. This will always be less than or equal to |maxfrag|. On | |
455 | * exit the record layer may update this to an alternative fragment size to | |
456 | * be used. This must always be less than or equal to |maxfrag|. | |
14b54475 | 457 | */ |
48cc4e0c MC |
458 | size_t (*get_max_records)(OSSL_RECORD_LAYER *rl, int type, size_t len, |
459 | size_t maxfrag, size_t *preffrag); | |
14b54475 MC |
460 | |
461 | /* | |
462 | * Write |numtempl| records from the array of record templates pointed to | |
463 | * by |templates|. Each record should be no longer than the value returned | |
464 | * by get_max_record_len(), and there should be no more records than the | |
465 | * value returned by get_max_records(). | |
14b54475 MC |
466 | * Where possible the caller will attempt to ensure that all records are the |
467 | * same length, except the last record. This may not always be possible so | |
468 | * the record method implementation should not rely on this being the case. | |
469 | * In the event of a retry the caller should call retry_write_records() | |
470 | * to try again. No more calls to write_records() should be attempted until | |
471 | * retry_write_records() returns success. | |
472 | * Buffers allocated for the record templates can be freed immediately after | |
473 | * write_records() returns - even in the case a retry. | |
474 | * The record templates represent the plaintext payload. The encrypted | |
475 | * output is written to the |transport| BIO. | |
476 | * Returns: | |
477 | * 1 on success | |
478 | * 0 on retry | |
479 | * -1 on failure | |
480 | */ | |
48cc4e0c MC |
481 | int (*write_records)(OSSL_RECORD_LAYER *rl, OSSL_RECORD_TEMPLATE *templates, |
482 | size_t numtempl); | |
14b54475 MC |
483 | |
484 | /* | |
485 | * Retry a previous call to write_records. The caller should continue to | |
486 | * call this until the function returns with success or failure. After | |
48cc4e0c | 487 | * each retry more of the data may have been incrementally sent. |
14b54475 MC |
488 | * Returns: |
489 | * 1 on success | |
490 | * 0 on retry | |
491 | * -1 on failure | |
492 | */ | |
48cc4e0c | 493 | int (*retry_write_records)(OSSL_RECORD_LAYER *rl); |
14b54475 MC |
494 | |
495 | /* | |
496 | * Read a record and return the record layer version and record type in | |
497 | * the |rversion| and |type| parameters. |*data| is set to point to a | |
498 | * record layer buffer containing the record payload data and |*datalen| | |
499 | * is filled in with the length of that data. The |epoch| and |seq_num| | |
500 | * values are only used if DTLS has been negotiated. In that case they are | |
501 | * filled in with the epoch and sequence number from the record. | |
502 | * An opaque record layer handle for the record is returned in |*rechandle| | |
503 | * which is used in a subsequent call to |release_record|. The buffer must | |
504 | * remain available until release_record is called. | |
505 | * | |
506 | * Internally the the OSSL_RECORD_METHOD the implementation may read/process | |
507 | * multiple records in one go and buffer them. | |
508 | */ | |
48cc4e0c MC |
509 | int (*read_record)(OSSL_RECORD_LAYER *rl, void **rechandle, int *rversion, |
510 | int *type, unsigned char **data, size_t *datalen, | |
511 | uint16_t *epoch, unsigned char *seq_num); | |
14b54475 MC |
512 | /* |
513 | * Release a buffer associated with a record previously read with | |
514 | * read_record. Records are guaranteed to be released in the order that they | |
515 | * are read. | |
516 | */ | |
48cc4e0c MC |
517 | int (*release_record)(OSSL_RECORD_LAYER *rl, void *rechandle); |
518 | ||
519 | /* | |
520 | * In the event that a fatal error is returned from the functions above then | |
521 | * get_alert_code() can be called to obtain a more details identifier for | |
522 | * the error. In (D)TLS this is the alert description code. | |
523 | */ | |
524 | int (*get_alert_code)(OSSL_RECORD_LAYER *rl); | |
525 | ||
526 | /* | |
527 | * Update the transport BIO from the one originally set in the | |
528 | * new_record_layer call | |
529 | */ | |
530 | int (*set1_bio)(OSSL_RECORD_LAYER *rl, BIO *bio); | |
531 | ||
532 | /* Called when protocol negotiation selects a protocol version to use */ | |
533 | int (*set_protocol_version)(OSSL_RECORD_LAYER *rl, int version); | |
534 | ||
535 | /* | |
536 | * Whether we are allowed to receive unencrypted alerts, even if we might | |
537 | * otherwise expect encrypted records. Ignored by protocol versions where | |
538 | * this isn't relevant | |
539 | */ | |
540 | void (*set_plain_alerts)(OSSL_RECORD_LAYER *rl, int allow); | |
14b54475 | 541 | |
48cc4e0c MC |
542 | /* |
543 | * Called immediately after creation of the record layer if we are in a | |
544 | * first handshake. Also called at the end of the first handshake | |
545 | */ | |
546 | void (*set_first_handshake)(OSSL_RECORD_LAYER *rl, int first); | |
547 | ||
548 | /* | |
549 | * Set the maximum number of pipelines that the record layer should process. | |
550 | * The default is 1. | |
551 | */ | |
552 | void (*set_max_pipelines)(OSSL_RECORD_LAYER *rl, size_t max_pipelines); | |
553 | ||
554 | /* | |
555 | * Called to tell the record layer whether we are currently "in init" or | |
556 | * not. Default at creation of the record layer is "yes". | |
557 | */ | |
558 | void (*set_in_init)(OSSL_RECORD_LAYER *rl, int in_init); | |
559 | ||
560 | /* | |
561 | * Get a short or long human readable description of the record layer state | |
562 | */ | |
563 | void (*get_state)(OSSL_RECORD_LAYER *rl, const char **shortstr, | |
564 | const char **longstr); | |
565 | ||
566 | /* | |
a53d4f83 | 567 | * Set new options or modify ones that were originally specified in the |
48cc4e0c MC |
568 | * new_record_layer call. |
569 | */ | |
570 | int (*set_options)(OSSL_RECORD_LAYER *rl, const OSSL_PARAM *options); | |
571 | ||
572 | const COMP_METHOD *(*get_compression)(OSSL_RECORD_LAYER *rl); | |
573 | ||
574 | /* | |
575 | * Set the maximum fragment length to be used for the record layer. This | |
576 | * will override any previous value supplied for the "max_frag_len" | |
577 | * setting during construction of the record layer. | |
578 | */ | |
579 | void (*set_max_frag_len)(OSSL_RECORD_LAYER *rl, size_t max_frag_len); | |
580 | ||
581 | /* | |
582 | * The maximum expansion in bytes that the record layer might add while | |
583 | * writing a record | |
584 | */ | |
585 | size_t (*get_max_record_overhead)(OSSL_RECORD_LAYER *rl); | |
586 | ||
587 | /* | |
588 | * Increment the record sequence number | |
589 | */ | |
590 | int (*increment_sequence_ctr)(OSSL_RECORD_LAYER *rl); | |
591 | ||
592 | /* | |
593 | * Allocate read or write buffers. Does nothing if already allocated. | |
594 | * Assumes default buffer length and 1 pipeline. | |
595 | */ | |
596 | int (*alloc_buffers)(OSSL_RECORD_LAYER *rl); | |
597 | ||
598 | /* | |
599 | * Free read or write buffers. Fails if there is pending read or write | |
600 | * data. Buffers are automatically reallocated on next read/write. | |
601 | */ | |
602 | int (*free_buffers)(OSSL_RECORD_LAYER *rl); | |
14b54475 MC |
603 | }; |
604 | ```` |