iPXE
tlsfmt.c File Reference

TLS data formats. More...

#include <string.h>
#include <errno.h>
#include <byteswap.h>
#include <ipxe/tls.h>
#include <ipxe/tlsfmt.h>

Go to the source code of this file.

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 FILE_SECBOOT (PERMITTED)
static const char * tls_map_name (const uint8_t *map)
 Get data structure descriptor mapping name (for debugging).
static int tls_parse_extensions (const uint8_t *map, unsigned int index, struct tls_cursor *fields, unsigned int count)
 Parse TLS extensions within a data structure.
int tls_parse_map (const uint8_t *map, unsigned int version, const struct tls_cursor *cursor, union tls_ptr_len *desc)
 Parse TLS data structure.
int tls_parse_opt_map (const uint8_t *map, unsigned int version, const struct tls_cursor *cursor, union tls_ptr_len *desc)
 Parse optional TLS data structure.
static int tls_build_extensions (const uint8_t *map, unsigned int index, struct tls_cursor *fields, unsigned int count)
 Build TLS extensions within a data structure.
int tls_build_map (const uint8_t *map, unsigned int version, union tls_ptr_len *desc, struct tls_cursor *cursor)
 Build TLS data structure.
int tls_size_map (const uint8_t *map, unsigned int version, union tls_ptr_len *desc, struct tls_cursor *cursor)
 Calculate length of TLS data structure.
 TLS_DESCR_MAPPING (tls_certificate)
 Certificate descriptor mapping.
 TLS_DESCR_MAPPING (tls_certificate_entry)
 CertificateEntry descriptor mapping.
 TLS_DESCR_MAPPING (tls_client_hello)
 ClientHello descriptor mapping.
 TLS_DESCR_MAPPING (tls_client_key_exchange_dhe)
 ClientKeyExchange descriptor mapping (for DHE).
 TLS_DESCR_MAPPING (tls_client_key_exchange_ecdhe)
 ClientKeyExchange descriptor mapping (for ECDHE).
 TLS_DESCR_MAPPING (tls_client_key_exchange_pubkey)
 ClientKeyExchange descriptor mapping (for key transport).
 TLS_DESCR_MAPPING (tls_digitally_signed)
 DigitallySigned descriptor mapping.
 TLS_DESCR_MAPPING (tls_extension)
 Extension descriptor mapping.
 TLS_DESCR_MAPPING (tls_hello_request)
 HelloRequest descriptor mapping.
 TLS_DESCR_MAPPING (tls_key_share_client_hello)
 KeyShareClientHello descriptor mapping.
 TLS_DESCR_MAPPING (tls_key_share_entry)
 KeyShareEntry descriptor mapping.
 TLS_DESCR_MAPPING (tls_key_share_hello_retry_request)
 KeyShareHelloRetryRequest descriptor mapping.
 TLS_DESCR_MAPPING (tls_key_share_server_hello)
 KeyShareServerHello descriptor mapping.
 TLS_DESCR_MAPPING (tls_max_fragment_length)
 MaxFragmentLength descriptor mapping.
 TLS_DESCR_MAPPING (tls_named_group_list)
 NamedGroupList descriptor mapping.
 TLS_DESCR_MAPPING (tls_new_session_ticket)
 NewSessionTicket descriptor mapping.
 TLS_DESCR_MAPPING (tls_psk_key_exchange_modes)
 PskKeyExchangeModes descriptor mapping.
 TLS_DESCR_MAPPING (tls_renegotiation_info)
 RenegotiationInfo descriptor mapping.
 TLS_DESCR_MAPPING (tls_server_hello)
 ServerHello descriptor mapping.
 TLS_DESCR_MAPPING (tls_server_hello_done)
 ServerHello descriptor mapping.
 TLS_DESCR_MAPPING (tls_server_key_exchange_dhe)
 ServerKeyExchange descriptor mapping (for DHE).
 TLS_DESCR_MAPPING (tls_server_key_exchange_ecdhe)
 ServerKeyExchange descriptor mapping (for ECDHE).
 TLS_DESCR_MAPPING (tls_server_name)
 ServerName descriptor mapping.
 TLS_DESCR_MAPPING (tls_server_name_list)
 ServerNameList descriptor mapping.
 TLS_DESCR_MAPPING (tls_signature_scheme_list)
 SignatureSchemeList descriptor mapping.
 TLS_DESCR_MAPPING (tls_supported_version)
 SupportedVersions descriptor mapping (in ServerHello).
 TLS_DESCR_MAPPING (tls_supported_versions)
 SupportedVersions descriptor mapping (in ClientHello).

Detailed Description

TLS data formats.

Definition in file tlsfmt.c.

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )

◆ FILE_SECBOOT()

FILE_SECBOOT ( PERMITTED )

◆ tls_map_name()

const char * tls_map_name ( const uint8_t * map)
static

Get data structure descriptor mapping name (for debugging).

Parameters
mapData structure descriptor mapping
Return values
nameData structure name

Definition at line 45 of file tlsfmt.c.

45 {
46
47 if ( map == tls_certificate_map ) {
48 return "Certificate";
49 } else if ( map == tls_certificate_entry_map ) {
50 return "CertificateEntry";
51 } else if ( map == tls_client_hello_map ) {
52 return "ClientHello";
53 } else if ( ( map == tls_client_key_exchange_dhe_map ) ||
54 ( map == tls_client_key_exchange_ecdhe_map ) ||
55 ( map == tls_client_key_exchange_pubkey_map ) ) {
56 return "ClientKeyExchange";
57 } else if ( map == tls_digitally_signed_map ) {
58 return "DigitallySigned";
59 } else if ( map == tls_extension_map ) {
60 return "Extension";
61 } else if ( map == tls_hello_request_map ) {
62 return "HelloRequest";
63 } else if ( map == tls_key_share_client_hello_map ) {
64 return "KeyShareClientHello";
65 } else if ( map == tls_key_share_entry_map ) {
66 return "KeyShareEntry";
67 } else if ( map == tls_key_share_hello_retry_request_map ) {
68 return "KeyShareHelloRetryRequest";
69 } else if ( map == tls_key_share_server_hello_map ) {
70 return "KeyShareServerHello";
71 } else if ( map == tls_max_fragment_length_map ) {
72 return "MaxFragmentLength";
73 } else if ( map == tls_named_group_list_map ) {
74 return "NamedGroupList";
75 } else if ( map == tls_new_session_ticket_map ) {
76 return "NewSessionTicket";
77 } else if ( map == tls_psk_key_exchange_modes_map ) {
78 return "PskKeyExchangeModes";
79 } else if ( map == tls_renegotiation_info_map ) {
80 return "RenegotiationInfo";
81 } else if ( map == tls_server_hello_map ) {
82 return "ServerHello";
83 } else if ( map == tls_server_hello_done_map ) {
84 return "ServerHelloDone";
85 } else if ( ( map == tls_server_key_exchange_dhe_map ) ||
86 ( map == tls_server_key_exchange_ecdhe_map ) ) {
87 return "ServerKeyExchange";
88 } else if ( map == tls_server_name_map ) {
89 return "ServerName";
90 } else if ( map == tls_server_name_list_map ) {
91 return "ServerNameList";
92 } else if ( map == tls_signature_scheme_list_map ) {
93 return "SignatureSchemeList";
94 } else if ( ( map == tls_supported_versions_map ) ||
95 ( map == tls_supported_version_map ) ) {
96 return "SupportedVersions";
97 } else {
98 return "<UNKNOWN>";
99 }
100}
static __always_inline int struct dma_mapping * map
Definition dma.h:184

References map.

Referenced by tls_build_extensions(), tls_build_map(), tls_parse_extensions(), tls_parse_map(), and tls_parse_opt_map().

◆ tls_parse_extensions()

int tls_parse_extensions ( const uint8_t * map,
unsigned int index,
struct tls_cursor * fields,
unsigned int count )
static

Parse TLS extensions within a data structure.

Parameters
mapData structure descriptor mapping
indexCurrent index within mapping
fieldsExtensions data fields
countNumber of extensions
Return values
rcReturn status code

Definition at line 111 of file tlsfmt.c.

113 {
114 const uint16_t __attribute__ (( aligned ( 1 ) )) *invtypes;
115 const struct tls_cursor *cursor = &fields[0];
116 struct tls_extension extension;
117 unsigned int i;
119 int rc;
120
121 /* Extension types are encoded as inverted */
122 invtypes = ( ( const void * ) &map[index] );
123 for ( i = 1 ; i <= count ; i++ ) {
124 if ( ! invtypes[i] ) {
125 DBGC ( map, "TLSFMT %s #%d mapping missing extension "
126 "%d\n", tls_map_name ( map ), index, i );
127 return -EINVAL;
128 }
129 }
130
131 /* Parse extensions */
132 for ( ; cursor->len ; cursor = &extension.next ) {
133
134 /* Parse next extension */
136 cursor, &extension ) ) != 0 )
137 return rc;
138
139 /* Scan for matching extensions */
140 for ( i = 1 ; i <= count ; i++ ) {
141 type = ~invtypes[i];
142 if ( type != *(extension.type) )
143 continue;
144 if ( fields[i].data ) {
145 DBGC ( map, "TLSFMT %s #%d has duplicate "
146 "extension %#04x\n",
148 ntohs ( type ) );
149 return -EPROTO;
150 }
151 fields[i].data = extension.data.data;
152 fields[i].len = extension.data.len;
153 DBGC2 ( map, "TLSFMT %s #%d extension %#04x len "
154 "%zd\n", tls_map_name ( map ), index,
155 ntohs ( type ), fields[i].len );
156 DBGC2_HDA ( map, 0, fields[i].data, fields[i].len );
157 }
158 }
159
160 return 0;
161}
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
unsigned short uint16_t
Definition stdint.h:11
long index
Definition bigint.h:30
ring len
Length.
Definition dwmac.h:226
uint32_t type
Operating system type.
Definition ena.h:1
uint8_t data[48]
Additional event data.
Definition ena.h:11
#define DBGC2(...)
Definition compiler.h:547
#define DBGC2_HDA(...)
Definition compiler.h:548
#define DBGC(...)
Definition compiler.h:530
static unsigned int count
Number of entries.
Definition dwmac.h:220
#define EINVAL
Invalid argument.
Definition errno.h:472
#define EPROTO
Protocol error.
Definition errno.h:668
#define ntohs(value)
Definition byteswap.h:137
#define __attribute__(x)
Definition compiler.h:10
A TLS variable-length data cursor.
Definition tlsfmt.h:186
void * data
Data.
Definition tlsfmt.h:188
size_t len
Length of data.
Definition tlsfmt.h:190
Extension descriptor.
Definition tlsfmt.h:499
static const char * tls_map_name(const uint8_t *map)
Get data structure descriptor mapping name (for debugging).
Definition tlsfmt.c:45
#define tls_parse(type, version, cursor, desc)
Parse TLS data structure.
Definition tlsfmt.h:733
#define TLS_VERSION_BASE
Lowest configurable supported version.
Definition tlsfmt.h:183

References __attribute__, count, data, tls_cursor::data, tls_extension::data, DBGC, DBGC2, DBGC2_HDA, EINVAL, EPROTO, index, len, tls_cursor::len, map, tls_extension::next, ntohs, rc, tls_map_name(), tls_parse, TLS_VERSION_BASE, tls_extension::type, and type.

Referenced by tls_parse_map().

◆ tls_parse_map()

int tls_parse_map ( const uint8_t * map,
unsigned int version,
const struct tls_cursor * cursor,
union tls_ptr_len * desc )

Parse TLS data structure.

Parameters
mapData structure descriptor mapping
versionProtocol version
cursorCursor containing TLS data structure
descData structure descriptor to fill in
Return values
rcReturn status code

Definition at line 172 of file tlsfmt.c.

174 {
175 struct tls_cursor *field;
176 void *data;
177 size_t remaining;
178 unsigned int count;
179 unsigned int index;
180 unsigned int next;
181 unsigned int byte;
182 unsigned int minimum;
183 unsigned int len_len;
184 unsigned int len;
185 int fixed;
186 int exts;
187 int rc;
188
189 /* Read initial cursor (may overlap output data structure) */
190 data = cursor->data;
191 remaining = cursor->len;
192 DBGC2 ( map, "TLSFMT %s parsing len %zd\n",
193 tls_map_name ( map ), remaining );
194 DBGC2_HDA ( map, 0, data, remaining );
195
196 /* Get mapping length */
197 count = map[0];
198 if ( ! count ) {
199 DBGC ( map, "TLSFMT %s mapping has no count\n",
200 tls_map_name ( map ) );
201 return -EINVAL;
202 }
203
204 /* Clear data structure descriptor */
205 memset ( desc, 0, ( ( count - 1 ) * sizeof ( desc[0] ) ) );
206
207 /* Parse data via mapping */
208 for ( index = 1 ; ( next = index ) < count ; index = next ) {
209
210 /* Prepare to store field description */
211 field = container_of ( &desc[ index - 1 ].data,
212 struct tls_cursor, data );
213
214 /* Interpret byte as `llllllvv` */
215 byte = map[next++];
216 minimum = TLS_MAP_MIN ( byte );
217 fixed = TLS_MAP_FIXED ( byte );
218 if ( fixed < 0 ) {
219 DBGC ( map, "TLSFMT %s #%d mapping missing\n",
220 tls_map_name ( map ), index );
221 return -EINVAL;
222 }
223 assert ( next <= count );
224
225 /* Handle fixed-length fields */
226 if ( fixed ) {
227 if ( version < minimum ) {
228 DBGC2 ( map, "TLSFMT %s #%d not in version "
229 "%d.%d\n", tls_map_name ( map ),
230 index, ( version >> 8 ),
231 ( version & 0xff ) );
232 continue;
233 }
234 if ( ( ( size_t ) fixed ) > remaining ) {
235 DBGC ( map, "TLSFMT %s #%d too short for "
236 "fixed length %d:\n",
237 tls_map_name ( map ), index, fixed );
238 DBGC_HDA ( map, 0, data, remaining );
239 return -EPROTO;
240 }
241 field->data = data;
242 DBGC2 ( map, "TLSFMT %s #%d len %d\n",
243 tls_map_name ( map ), index, fixed );
244 DBGC2_HDA ( map, 0, field->data, fixed );
245 data += fixed;
246 remaining -= fixed;
247 continue;
248 }
249
250 /* Interpret next byte as `xxxxxxnn` */
251 if ( next >= count ) {
252 DBGC ( map, "TLSFMT %s #%d mapping overrun\n",
253 tls_map_name ( map ), index );
254 return -EINVAL;
255 }
256 byte = map[next++];
257 len_len = TLS_MAP_LEN_LEN ( byte );
258 exts = TLS_MAP_EXTENSIONS ( byte );
259 if ( exts >= 0 )
260 next += ( exts * 2 );
261 if ( next > count ) {
262 DBGC ( map, "TLSFMT %s #%d mapping extensions "
263 "overrun\n", tls_map_name ( map ), index );
264 return -EINVAL;
265 }
266 if ( version < minimum ) {
267 DBGC2 ( map, "TLSFMT %s #%d not in version %d.%d\n",
268 tls_map_name ( map ), index, ( version >> 8 ),
269 ( version & 0xff ) );
270 continue;
271 }
272
273 /* Allow for optional extensions fields */
274 if ( ( exts >= 0 ) && ( ! remaining ) &&
276 DBGC2 ( map, "TLSFMT %s #%d optional in version "
277 "%d.%d\n", tls_map_name ( map ), index,
278 ( version >> 8 ), ( version & 0xff ) );
279 continue;
280 }
281
282 /* Handle variable-length fields */
283 if ( remaining < len_len ) {
284 DBGC ( map, "TLSFMT %s #%d too short for %d-byte "
285 "variable length:\n", tls_map_name ( map ),
286 index, len_len );
287 DBGC_HDA ( map, 0, data, remaining );
288 return -EPROTO;
289 }
290 if ( len_len ) {
291 for ( len = 0 ; len_len ; len_len-- ) {
292 len <<= 8;
293 len |= *( ( const uint8_t * ) data++ );
294 remaining--;
295 }
296 } else {
297 len = remaining;
298 }
299 if ( remaining < len ) {
300 DBGC ( map, "TLSFMT %s #%d too short for variable "
301 "length %d:\n",
302 tls_map_name ( map ), index, len );
303 DBGC_HDA ( map, 0, data, remaining );
304 return -EPROTO;
305 }
306 field->data = data;
307 field->len = len;
308 DBGC2 ( map, "TLSFMT %s #%d len %zd\n",
309 tls_map_name ( map ), index, field->len );
310 DBGC2_HDA ( map, 0, field->data, field->len );
311 data += len;
312 remaining -= len;
313 if ( exts < 0 )
314 continue;
315
316 /* Handle fields containing extensions */
317 if ( ( rc = tls_parse_extensions ( map, index, field,
318 exts ) ) != 0 ) {
319 return rc;
320 }
321 }
322
323 /* Check that all data was consumed */
324 if ( remaining ) {
325 DBGC ( map, "TLSFMT %s has excess data:\n",
326 tls_map_name ( map ) );
327 DBGC_HDA ( map, 0, data, remaining );
328 return -EPROTO;
329 }
330
331 return 0;
332}
unsigned char uint8_t
Definition stdint.h:10
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:61
u32 version
Driver version.
Definition ath9k_hw.c:1985
uint32_t next
Next descriptor address.
Definition dwmac.h:11
struct eltorito_descriptor_fixed fixed
Fixed portion.
Definition eltorito.h:1
struct ena_llq_option desc
Descriptor counts.
Definition ena.h:9
#define DBGC_HDA(...)
Definition compiler.h:531
void * memset(void *dest, int character, size_t len) __nonnull
unsigned char byte
Definition smc9000.h:38
#define container_of(ptr, type, field)
Get containing structure.
Definition stddef.h:36
static int tls_parse_extensions(const uint8_t *map, unsigned int index, struct tls_cursor *fields, unsigned int count)
Parse TLS extensions within a data structure.
Definition tlsfmt.c:111
#define TLS_MAP_FIXED(byte)
Interpret fixed length from an llllllvv byte.
Definition tlsfmt.h:370
#define TLS_VERSION_TLS_1_3
TLS version 1.3.
Definition tlsfmt.h:180
#define TLS_MAP_EXTENSIONS(byte)
Interpret number of extensions from an xxxxxxnn byte.
Definition tlsfmt.h:389
#define TLS_MAP_MIN(byte)
Interpret minimum version from an llllllvv byte.
Definition tlsfmt.h:362
#define TLS_MAP_LEN_LEN(byte)
Interpret number of length bytes from an xxxxxxnn byte.
Definition tlsfmt.h:378

References assert, container_of, count, data, tls_cursor::data, DBGC, DBGC2, DBGC2_HDA, DBGC_HDA, desc, EINVAL, EPROTO, fixed, index, len, tls_cursor::len, map, memset(), next, rc, TLS_MAP_EXTENSIONS, TLS_MAP_FIXED, TLS_MAP_LEN_LEN, TLS_MAP_MIN, tls_map_name(), tls_parse_extensions(), TLS_VERSION_TLS_1_3, and version.

Referenced by tls_parse_opt_map().

◆ tls_parse_opt_map()

int tls_parse_opt_map ( const uint8_t * map,
unsigned int version,
const struct tls_cursor * cursor,
union tls_ptr_len * desc )

Parse optional TLS data structure.

Parameters
mapData structure descriptor mapping
versionProtocol version
cursorCursor containing TLS data structure
descData structure descriptor to fill in
Return values
rcReturn status code

Definition at line 343 of file tlsfmt.c.

345 {
346 unsigned int count;
347 int rc;
348
349 /* Get mapping length */
350 count = map[0];
351 if ( ! count ) {
352 DBGC ( map, "TLSFMT %s mapping has no count\n",
353 tls_map_name ( map ) );
354 return -EINVAL;
355 }
356
357 /* Clear data structure descriptor */
358 memset ( desc, 0, ( ( count - 1 ) * sizeof ( desc[0] ) ) );
359
360 /* Do nothing if optional data structure is not present */
361 if ( ! cursor->data )
362 return 0;
363
364 /* Parse data structure */
365 if ( ( rc = tls_parse_map ( map, version, cursor, desc ) ) != 0 )
366 return rc;
367
368 return 0;
369}
int tls_parse_map(const uint8_t *map, unsigned int version, const struct tls_cursor *cursor, union tls_ptr_len *desc)
Parse TLS data structure.
Definition tlsfmt.c:172

References count, tls_cursor::data, DBGC, desc, EINVAL, map, memset(), rc, tls_map_name(), tls_parse_map(), and version.

Referenced by tls_new_server_hello().

◆ tls_build_extensions()

int tls_build_extensions ( const uint8_t * map,
unsigned int index,
struct tls_cursor * fields,
unsigned int count )
static

Build TLS extensions within a data structure.

Parameters
mapData structure descriptor mapping
indexCurrent index within mapping
fieldsExtensions data fields
countNumber of extensions
Return values
rcReturn status code

Definition at line 380 of file tlsfmt.c.

382 {
383 const uint16_t __attribute__ (( aligned ( 1 ) )) *invtypes;
384 struct tls_cursor *cursor = &fields[0];
385 struct tls_cursor *subcursor;
386 struct tls_extension extension;
387 unsigned int i;
389 int rc;
390
391 /* Prepare per-extension subcursor */
392 subcursor = &extension.next;
393 subcursor->data = cursor->data;
394 cursor->len = 0;
395
396 /* Extension types are encoded as inverted */
397 invtypes = ( ( const void * ) &map[index] );
398 for ( i = 1 ; i <= count ; i++ ) {
399 if ( ! invtypes[i] ) {
400 DBGC ( map, "TLSFMT %s #%d mapping missing extension "
401 "%d\n", tls_map_name ( map ), index, i );
402 return -EINVAL;
403 }
404 }
405
406 /* Build extensions */
407 for ( i = 1 ; i <= count ; i++ ) {
408
409 /* Skip extensions that will not be included */
410 if ( ! ( fields[i].data || fields[i].len ) )
411 continue;
412
413 /* Build extension */
414 type = ~invtypes[i];
415 extension.type = &type;
416 extension.data = fields[i];
417 extension.next.len = 0;
419 &extension, subcursor ) ) != 0 ) {
420 return rc;
421 }
422 fields[i].len = extension.data.len;
423 DBGC2 ( map, "TLSFMT %s #%d extension %#04x len %zd\n",
424 tls_map_name ( map ), index, ntohs ( type ),
425 fields[i].len );
426 cursor->len += subcursor->len;
427 if ( cursor->data ) {
428 fields[i].data = extension.data.data;
429 DBGC2_HDA ( map, 0, fields[i].data, fields[i].len );
430 }
431 }
432
433 return 0;
434}
#define tls_build(type, version, desc, cursor)
Build TLS data structure.
Definition tlsfmt.h:763

References __attribute__, count, data, tls_cursor::data, tls_extension::data, DBGC, DBGC2, DBGC2_HDA, EINVAL, index, len, tls_cursor::len, map, tls_extension::next, ntohs, rc, tls_build, tls_map_name(), TLS_VERSION_BASE, tls_extension::type, and type.

Referenced by tls_build_map().

◆ tls_build_map()

int tls_build_map ( const uint8_t * map,
unsigned int version,
union tls_ptr_len * desc,
struct tls_cursor * cursor )

Build TLS data structure.

Parameters
mapData structure descriptor mapping
versionProtocol version
descData structure descriptor
cursorCursor to contain TLS data structure
Return values
rcReturn status code

Build a TLS data structure at the cursor. The cursor's original length will be ignored and will be set to the overall length of the built data structure. The caller must ensure that sufficient space already exists (e.g. by calling tls_size() first to determine the required length).

The overall length will be calculated based on the variable lengths within the descriptor. The output content will be be copied from any non-NULL pointers within the descriptor (with any missing content initialised to zero).

Pointers within the descriptor will be updated to point to the appropriate location within the built data structure.

The caller must therefore fill in any variable lengths within the descriptor beforehand, but may freely choose to either fill in pointers within the descriptor beforehand or to write through the updated pointers afterwards.

A cursor with a NULL data pointer may be used to calculate the required length without copying in any data or updating any pointers within the descriptor.

Definition at line 468 of file tlsfmt.c.

469 {
470 struct tls_cursor *field;
471 void *data;
472 size_t len;
473 size_t max;
474 unsigned int count;
475 unsigned int index;
476 unsigned int next;
477 unsigned int byte;
478 unsigned int minimum;
479 unsigned int len_len;
480 int fixed;
481 int exts;
482 int rc;
483
484 /* Read initial cursor (may overlap output data structure) */
485 data = cursor->data;
486 len = 0;
487
488 /* Get mapping length */
489 count = map[0];
490 if ( ! count ) {
491 DBGC ( map, "TLSFMT %s mapping has no count\n",
492 tls_map_name ( map ) );
493 return -EINVAL;
494 }
495
496 /* Accumulate total length via mapping */
497 for ( index = 1 ; ( next = index ) < count ; index = next ) {
498
499 /* Prepare to read field description */
500 field = container_of ( &desc[ index - 1 ].data,
501 struct tls_cursor, data );
502
503 /* Interpret byte as `llllllvv` */
504 byte = map[next++];
505 minimum = TLS_MAP_MIN ( byte );
506 fixed = TLS_MAP_FIXED ( byte );
507 if ( fixed < 0 ) {
508 DBGC ( map, "TLSFMT %s #%d mapping missing\n",
509 tls_map_name ( map ), index );
510 return -EINVAL;
511 }
512 assert ( next <= count );
513
514 /* Handle fixed-length fields */
515 if ( fixed ) {
516 if ( version < minimum ) {
517 DBGC2 ( map, "TLSFMT %s #%d not in version "
518 "%d.%d\n", tls_map_name ( map ),
519 index, ( version >> 8 ),
520 ( version & 0xff ) );
521 continue;
522 }
523 DBGC2 ( map, "TLSFMT %s #%d len %d\n",
524 tls_map_name ( map ), index, fixed );
525 len += fixed;
526 if ( data ) {
527 if ( field->data ) {
528 memcpy ( data, field->data, fixed );
529 } else {
530 memset ( data, 0, fixed );
531 }
532 field->data = data;
533 data += fixed;
534 DBGC2_HDA ( map, 0, field->data, fixed );
535 }
536 continue;
537 }
538
539 /* Interpret next byte as `xxxxxxnn` */
540 if ( next >= count ) {
541 DBGC ( map, "TLSFMT %s #%d mapping overrun\n",
542 tls_map_name ( map ), index );
543 return -EINVAL;
544 }
545 byte = map[next++];
546 len_len = TLS_MAP_LEN_LEN ( byte );
547 exts = TLS_MAP_EXTENSIONS ( byte );
548 if ( exts >= 0 )
549 next += ( exts * 2 );
550 if ( next > count ) {
551 DBGC ( map, "TLSFMT %s #%d mapping extensions "
552 "overrun\n", tls_map_name ( map ), index );
553 return -EINVAL;
554 }
555 if ( version < minimum ) {
556 DBGC2 ( map, "TLSFMT %s #%d not in version %d.%d\n",
557 tls_map_name ( map ), index, ( version >> 8 ),
558 ( version & 0xff ) );
559 continue;
560 }
561
562 /* Handle variable-length fields */
563 max = ( len_len ? ( ( 1 << ( 8 * len_len ) ) - 1 ) :
564 ( ( 1 << ( 8 * TLS_MAP_LEN_LEN_MAX ) ) - 1 ) );
565 if ( exts >= 0 ) {
566 field->data = ( data ? ( data + len_len ) : NULL );
567 if ( ( rc = tls_build_extensions ( map, index, field,
568 exts ) ) != 0 ) {
569 return rc;
570 }
571 }
572 if ( field->len > max ) {
573 DBGC ( map, "TLSFMT %s #%d len %zd too long\n",
574 tls_map_name ( map ), index, field->len );
575 return -ERANGE;
576 }
577
578 /* Allow for optional extensions fields */
579 if ( ( exts >= 0 ) && ( ! field->len ) &&
581 DBGC2 ( map, "TLSFMT %s #%d optional in version "
582 "%d.%d\n", tls_map_name ( map ), index,
583 ( version >> 8 ), ( version & 0xff ) );
584 continue;
585 }
586
587 /* Build field */
588 DBGC2 ( map, "TLSFMT %s #%d len %zd\n",
589 tls_map_name ( map ), index, field->len );
590 len += ( len_len + field->len );
591 if ( data ) {
592 while ( len_len-- ) {
593 *( ( uint8_t * ) data++ ) =
594 ( field->len >> ( 8 * len_len ) );
595 }
596 if ( exts < 0 ) {
597 if ( field->data ) {
598 memcpy ( data, field->data,
599 field->len );
600 } else {
601 memset ( data, 0, field->len );
602 }
603 }
604 field->data = data;
605 data += field->len;
606 DBGC2_HDA ( map, 0, field->data, field->len );
607 }
608 }
609
610 /* Update cursor (may overlap output data structure) */
611 cursor->len = len;
612 DBGC2 ( map, "TLSFMT %s built len %zd\n",
613 tls_map_name ( map ), cursor->len );
614 if ( data )
615 DBGC2_HDA ( map, 0, ( data - cursor->len ), cursor->len );
616
617 return 0;
618}
#define NULL
NULL pointer (VOID *).
Definition Base.h:321
#define max(x, y)
Definition ath.h:41
#define ERANGE
Result too large.
Definition errno.h:683
void * memcpy(void *dest, const void *src, size_t len) __nonnull
static int tls_build_extensions(const uint8_t *map, unsigned int index, struct tls_cursor *fields, unsigned int count)
Build TLS extensions within a data structure.
Definition tlsfmt.c:380
#define TLS_MAP_LEN_LEN_MAX
Maximum number of length bytes.
Definition tlsfmt.h:381

References assert, container_of, count, data, tls_cursor::data, DBGC, DBGC2, DBGC2_HDA, desc, EINVAL, ERANGE, fixed, index, len, tls_cursor::len, map, max, memcpy(), memset(), next, NULL, rc, tls_build_extensions(), TLS_MAP_EXTENSIONS, TLS_MAP_FIXED, TLS_MAP_LEN_LEN, TLS_MAP_LEN_LEN_MAX, TLS_MAP_MIN, tls_map_name(), TLS_VERSION_TLS_1_3, and version.

Referenced by tls_send_client_key_exchange(), and tls_size_map().

◆ tls_size_map()

int tls_size_map ( const uint8_t * map,
unsigned int version,
union tls_ptr_len * desc,
struct tls_cursor * cursor )

Calculate length of TLS data structure.

Parameters
typeDescriptor structure name
versionProtocol version
descData structure descriptor to fill in
cursorCursor to contain TLS data structure
Return values
rcReturn status code

The cursor size will be set to the overall length required to contain the TLS data structure, and the cursor data pointer will be set to NULL.

If this function returns successfully, then a subsequent call to tls_build() with the exact same inputs is guaranteed to succeed and need not be checked for an error return status. The data structure descriptor must not be modified in any way that would affect its length before calling tls_build(): the easiest way to ensure this is to not modify the data structure descriptor at all.

If this function fails, then the cursor length will be set to a value that is too large to be represented by a 24-bit length field. If the cursor itself lies within a containing data structure descriptor (e.g. if tls_size() is being used to calculate the size of an extension within a ClientHello descriptor), then this guarantees that a subsequent call to tls_size() on the containing descriptor will also fail. The caller therefore need only check the return status code from the call to tls_size() for the outermost descriptor.

Note that this optimisation applies only when the result cursor lies within a containing data structure descriptor and so is guaranteed to be consumed by a subsequent call to calculate the length of that containing TLS data structure. If a caller is using the result from tls_size() in any other way (e.g. to add up the lengths of a sequence of CertificateEntry structures), then the caller must check the return status code in the normal way.

Definition at line 658 of file tlsfmt.c.

659 {
660 int rc;
661
662 /* Calculate length */
663 cursor->data = NULL;
664 if ( ( rc = tls_build_map ( map, version, desc, cursor ) ) != 0 ) {
665 /* Set an uncontainable length on error */
666 cursor->len = -1UL;
667 return rc;
668 }
669
670 return 0;
671}
int tls_build_map(const uint8_t *map, unsigned int version, union tls_ptr_len *desc, struct tls_cursor *cursor)
Build TLS data structure.
Definition tlsfmt.c:468

References tls_cursor::data, desc, tls_cursor::len, map, NULL, rc, tls_build_map(), and version.

Referenced by tls_send_client_key_exchange().

◆ TLS_DESCR_MAPPING() [1/27]

TLS_DESCR_MAPPING ( tls_certificate )

Certificate descriptor mapping.

References TLS_MAPSZ, TLS_VAR08, TLS_VAR24, TLS_VERSION_BASE, and TLS_VERSION_TLS_1_3.

◆ TLS_DESCR_MAPPING() [2/27]

TLS_DESCR_MAPPING ( tls_certificate_entry )

CertificateEntry descriptor mapping.

References ext, next, TLS_EXT16, TLS_EXTRA, TLS_MAPSZ, TLS_VAR24, TLS_VERSION_BASE, and TLS_VERSION_TLS_1_3.

◆ TLS_DESCR_MAPPING() [3/27]

◆ TLS_DESCR_MAPPING() [4/27]

TLS_DESCR_MAPPING ( tls_client_key_exchange_dhe )

ClientKeyExchange descriptor mapping (for DHE).

References TLS_MAPSZ, TLS_VAR16, and TLS_VERSION_BASE.

◆ TLS_DESCR_MAPPING() [5/27]

TLS_DESCR_MAPPING ( tls_client_key_exchange_ecdhe )

ClientKeyExchange descriptor mapping (for ECDHE).

References TLS_MAPSZ, TLS_VAR08, and TLS_VERSION_BASE.

◆ TLS_DESCR_MAPPING() [6/27]

TLS_DESCR_MAPPING ( tls_client_key_exchange_pubkey )

ClientKeyExchange descriptor mapping (for key transport).

References TLS_MAPSZ, TLS_VAR16, and TLS_VERSION_BASE.

◆ TLS_DESCR_MAPPING() [7/27]

TLS_DESCR_MAPPING ( tls_digitally_signed )

DigitallySigned descriptor mapping.

References sig, TLS_FIXED, TLS_MAPSZ, TLS_VAR16, TLS_VERSION_BASE, and TLS_VERSION_TLS_1_2.

◆ TLS_DESCR_MAPPING() [8/27]

TLS_DESCR_MAPPING ( tls_extension )

Extension descriptor mapping.

References data, next, TLS_EXTRA, TLS_FIXED, TLS_MAPSZ, TLS_VAR16, TLS_VERSION_BASE, and type.

◆ TLS_DESCR_MAPPING() [9/27]

TLS_DESCR_MAPPING ( tls_hello_request )

HelloRequest descriptor mapping.

References TLS_MAPSZ.

◆ TLS_DESCR_MAPPING() [10/27]

TLS_DESCR_MAPPING ( tls_key_share_client_hello )

KeyShareClientHello descriptor mapping.

References TLS_MAPSZ, TLS_VAR16, and TLS_VERSION_BASE.

◆ TLS_DESCR_MAPPING() [11/27]

TLS_DESCR_MAPPING ( tls_key_share_entry )

KeyShareEntry descriptor mapping.

References group, next, TLS_EXTRA, TLS_FIXED, TLS_MAPSZ, TLS_VAR16, and TLS_VERSION_BASE.

◆ TLS_DESCR_MAPPING() [12/27]

TLS_DESCR_MAPPING ( tls_key_share_hello_retry_request )

KeyShareHelloRetryRequest descriptor mapping.

References group, TLS_FIXED, TLS_MAPSZ, and TLS_VERSION_BASE.

◆ TLS_DESCR_MAPPING() [13/27]

TLS_DESCR_MAPPING ( tls_key_share_server_hello )

KeyShareServerHello descriptor mapping.

References group, TLS_FIXED, TLS_MAPSZ, TLS_VAR16, and TLS_VERSION_BASE.

◆ TLS_DESCR_MAPPING() [14/27]

TLS_DESCR_MAPPING ( tls_max_fragment_length )

MaxFragmentLength descriptor mapping.

References max, TLS_FIXED, TLS_MAPSZ, and TLS_VERSION_BASE.

◆ TLS_DESCR_MAPPING() [15/27]

TLS_DESCR_MAPPING ( tls_named_group_list )

NamedGroupList descriptor mapping.

References TLS_MAPSZ, TLS_VAR16, and TLS_VERSION_BASE.

◆ TLS_DESCR_MAPPING() [16/27]

TLS_DESCR_MAPPING ( tls_new_session_ticket )

NewSessionTicket descriptor mapping.

References age, ext, lifetime, nonce, TLS_EXT16, TLS_FIXED, TLS_MAPSZ, TLS_VAR08, TLS_VAR16, TLS_VERSION_BASE, and TLS_VERSION_TLS_1_3.

◆ TLS_DESCR_MAPPING() [17/27]

TLS_DESCR_MAPPING ( tls_psk_key_exchange_modes )

PskKeyExchangeModes descriptor mapping.

References TLS_MAPSZ, TLS_VAR08, and TLS_VERSION_TLS_1_3.

◆ TLS_DESCR_MAPPING() [18/27]

TLS_DESCR_MAPPING ( tls_renegotiation_info )

RenegotiationInfo descriptor mapping.

References TLS_MAPSZ, TLS_VAR08, and TLS_VERSION_BASE.

◆ TLS_DESCR_MAPPING() [19/27]

◆ TLS_DESCR_MAPPING() [20/27]

TLS_DESCR_MAPPING ( tls_server_hello_done )

ServerHello descriptor mapping.

References TLS_MAPSZ.

◆ TLS_DESCR_MAPPING() [21/27]

TLS_DESCR_MAPPING ( tls_server_key_exchange_dhe )

ServerKeyExchange descriptor mapping (for DHE).

References TLS_EXTRA, TLS_MAPSZ, TLS_VAR16, and TLS_VERSION_BASE.

◆ TLS_DESCR_MAPPING() [22/27]

TLS_DESCR_MAPPING ( tls_server_key_exchange_ecdhe )

ServerKeyExchange descriptor mapping (for ECDHE).

References TLS_EXTRA, TLS_FIXED, TLS_MAPSZ, TLS_VAR08, and TLS_VERSION_BASE.

◆ TLS_DESCR_MAPPING() [23/27]

TLS_DESCR_MAPPING ( tls_server_name )

ServerName descriptor mapping.

References name, TLS_FIXED, TLS_MAPSZ, TLS_VAR16, TLS_VERSION_BASE, and type.

◆ TLS_DESCR_MAPPING() [24/27]

TLS_DESCR_MAPPING ( tls_server_name_list )

ServerNameList descriptor mapping.

References TLS_MAPSZ, TLS_VAR16, and TLS_VERSION_BASE.

◆ TLS_DESCR_MAPPING() [25/27]

TLS_DESCR_MAPPING ( tls_signature_scheme_list )

SignatureSchemeList descriptor mapping.

References TLS_MAPSZ, TLS_VAR16, and TLS_VERSION_BASE.

◆ TLS_DESCR_MAPPING() [26/27]

TLS_DESCR_MAPPING ( tls_supported_version )

SupportedVersions descriptor mapping (in ServerHello).

References TLS_FIXED, TLS_MAPSZ, and TLS_VERSION_BASE.

◆ TLS_DESCR_MAPPING() [27/27]

TLS_DESCR_MAPPING ( tls_supported_versions )

SupportedVersions descriptor mapping (in ClientHello).

References TLS_MAPSZ, TLS_VAR08, and TLS_VERSION_BASE.