Skip to content

Commit

Permalink
Move client hello parsing out of unstable (#4359)
Browse files Browse the repository at this point in the history
  • Loading branch information
lrstewart authored Jan 18, 2024
1 parent d573ce2 commit 028d315
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 27 deletions.
29 changes: 29 additions & 0 deletions api/s2n.h
Original file line number Diff line number Diff line change
Expand Up @@ -1393,6 +1393,35 @@ struct s2n_client_hello;
*/
S2N_API extern struct s2n_client_hello *s2n_connection_get_client_hello(struct s2n_connection *conn);

/**
* Creates an s2n_client_hello from bytes representing a ClientHello message.
*
* The input bytes should include the message header (message type and length),
* but not the record header.
*
* Unlike s2n_connection_get_client_hello, the s2n_client_hello returned by this
* method is owned by the application and must be freed with s2n_client_hello_free.
*
* This method does not support SSLv2 ClientHellos.
*
* @param bytes The raw bytes representing the ClientHello.
* @param size The size of raw_message.
* @returns A new s2n_client_hello on success, or NULL on failure.
*/
S2N_API extern struct s2n_client_hello *s2n_client_hello_parse_message(const uint8_t *bytes, uint32_t size);

/**
* Frees an s2n_client_hello structure.
*
* This method should be called to free s2n_client_hellos returned by
* s2n_client_hello_parse_message. It will error if passed an s2n_client_hello
* returned by s2n_connection_get_client_hello and owned by the connection.
*
* @param ch The structure to be freed.
* @returns S2N_SUCCESS on success, S2N_FAILURE on failure.
*/
S2N_API extern int s2n_client_hello_free(struct s2n_client_hello **ch);

/**
* Function to determine the size of the raw Client Hello buffer.
*
Expand Down
26 changes: 0 additions & 26 deletions api/unstable/fingerprint.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,29 +74,3 @@ S2N_API int s2n_client_hello_get_fingerprint_hash(struct s2n_client_hello *ch,
S2N_API int s2n_client_hello_get_fingerprint_string(struct s2n_client_hello *ch,
s2n_fingerprint_type type, uint32_t max_size,
uint8_t *output, uint32_t *output_size);

/**
* Creates an s2n_client_hello from bytes representing a ClientHello message.
*
* Unlike s2n_connection_get_client_hello, the s2n_client_hello returned by this
* method is owned by the application and must be freed with s2n_client_hello_free.
*
* This method does not support SSLv2 ClientHellos.
*
* @param bytes The raw bytes representing the ClientHello.
* @param size The size of raw_message.
* @returns A new s2n_client_hello on success, or NULL on failure.
*/
S2N_API struct s2n_client_hello *s2n_client_hello_parse_message(const uint8_t *bytes, uint32_t size);

/**
* Frees an s2n_client_hello structure.
*
* This method should be called to free s2n_client_hellos returned by
* s2n_client_hello_parse_message. It will error if passed an s2n_client_hello
* returned by s2n_connection_get_client_hello and owned by the connection.
*
* @param ch The structure to be freed.
* @returns S2N_SUCCESS on success, S2N_FAILURE on failure.
*/
S2N_API int s2n_client_hello_free(struct s2n_client_hello **ch);
18 changes: 17 additions & 1 deletion docs/usage-guide/topics/ch10-client-hello.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,30 @@
# Examining the Client Hello

## Getting a Client Hello

### From a connection
s2n-tls stores the received Client Hello and makes it available to the application. Call `s2n_connection_get_client_hello()` to get a pointer to the `s2n_client_hello` struct storing the Client Hello message. A NULL value will be returned if the connection has not yet received the Client Hello. The earliest point in the handshake when this struct is available is during the [Client Hello Callback](#client-hello-callback). The stored Client Hello message will not be available after calling `s2n_connection_free_handshake()`.

### From raw bytes
s2n-tls can parse a Client Hello from raw bytes. Call `s2n_client_hello_parse_message()`
with raw bytes representing a Client Hello message (including the message header, but excluding
the record header). The returned pointer to a `s2n_client_hello` struct behaves
the same as a pointer returned from `s2n_connection_get_client_hello()`, except
that the memory is owned by the application and must be freed with `s2n_client_hello_free()`.

## Examining the message

Call `s2n_client_hello_get_raw_message()` to retrieve the complete Client Hello message with the random bytes on it zeroed out.

Call `s2n_client_hello_get_cipher_suites()` to retrieve the list of cipher suites sent by the client.

Call `s2n_client_hello_get_session_id()` to retrieve the session ID sent by the client in the ClientHello message. Note that this value may not be the session ID eventually associated with this particular connection since the session ID can change when the server sends the Server Hello. The official session ID can be retrieved with `s2n_connection_get_session_id()`after the handshake completes.

Call `s2n_client_hello_get_extensions()` to retrieve the entire list of extensions sent in the Client Hello. Calling `s2n_client_hello_get_extension_by_id()` allows you to interrogate the `s2n_client_hello` struct for a specific extension.
Call `s2n_client_hello_get_extensions()` to retrieve the entire list of extensions sent in the Client Hello. Call `s2n_client_hello_get_extension_by_id()` to retrieve a specific extension. Because `s2n_client_hello_get_extension_by_id()` doesn't distinguish between zero-length extensions and missing extensions,
`s2n_client_hello_has_extension()` should be used to check for the existence of an extension.

Call `s2n_client_hello_get_supported_groups()` to retrieve the entire list of
supported groups sent by the client.

## SSLv2
s2n-tls will not negotiate SSLv2, but will accept SSLv2 ClientHellos advertising a
Expand Down

0 comments on commit 028d315

Please sign in to comment.