iPXE
tls.c File Reference

Transport Layer Security Protocol. More...

#include <stdint.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <byteswap.h>
#include <ipxe/pending.h>
#include <ipxe/hmac.h>
#include <ipxe/md5_sha1.h>
#include <ipxe/iobuf.h>
#include <ipxe/xfer.h>
#include <ipxe/open.h>
#include <ipxe/x509.h>
#include <ipxe/privkey.h>
#include <ipxe/certstore.h>
#include <ipxe/rootcert.h>
#include <ipxe/validator.h>
#include <ipxe/job.h>
#include <ipxe/ffdhe.h>
#include <ipxe/tls.h>
#include <config/crypto.h>

Go to the source code of this file.

Macros

#define EINVAL_CHANGE_CIPHER   __einfo_error ( EINFO_EINVAL_CHANGE_CIPHER )
#define EINFO_EINVAL_CHANGE_CIPHER
#define EINVAL_ALERT   __einfo_error ( EINFO_EINVAL_ALERT )
#define EINFO_EINVAL_ALERT
#define EINVAL_IV   __einfo_error ( EINFO_EINVAL_IV )
#define EINFO_EINVAL_IV
#define EINVAL_PADDING   __einfo_error ( EINFO_EINVAL_PADDING )
#define EINFO_EINVAL_PADDING
#define EINVAL_RX_STATE   __einfo_error ( EINFO_EINVAL_RX_STATE )
#define EINFO_EINVAL_RX_STATE
#define EINVAL_MAC   __einfo_error ( EINFO_EINVAL_MAC )
#define EINFO_EINVAL_MAC
#define EINVAL_KEY_EXCHANGE   __einfo_error ( EINFO_EINVAL_KEY_EXCHANGE )
#define EINFO_EINVAL_KEY_EXCHANGE
#define EINVAL_INNER   __einfo_error ( EINFO_EINVAL_INNER )
#define EINFO_EINVAL_INNER
#define EINVAL_BLOCK   __einfo_error ( EINFO_EINVAL_BLOCK )
#define EINFO_EINVAL_BLOCK
#define EIO_ALERT   __einfo_error ( EINFO_EIO_ALERT )
#define EINFO_EIO_ALERT
#define ENOENT_CERT   __einfo_error ( EINFO_ENOENT_CERT )
#define EINFO_ENOENT_CERT
#define ENOENT_KEY_EXCHANGE   __einfo_error ( EINFO_ENOENT_KEY_EXCHANGE )
#define EINFO_ENOENT_KEY_EXCHANGE
#define ENOMEM_CONTEXT   __einfo_error ( EINFO_ENOMEM_CONTEXT )
#define EINFO_ENOMEM_CONTEXT
#define ENOMEM_CERTIFICATE   __einfo_error ( EINFO_ENOMEM_CERTIFICATE )
#define EINFO_ENOMEM_CERTIFICATE
#define ENOMEM_CHAIN   __einfo_error ( EINFO_ENOMEM_CHAIN )
#define EINFO_ENOMEM_CHAIN
#define ENOMEM_TX_PLAINTEXT   __einfo_error ( EINFO_ENOMEM_TX_PLAINTEXT )
#define EINFO_ENOMEM_TX_PLAINTEXT
#define ENOMEM_TX_CIPHERTEXT   __einfo_error ( EINFO_ENOMEM_TX_CIPHERTEXT )
#define EINFO_ENOMEM_TX_CIPHERTEXT
#define ENOMEM_RX_DATA   __einfo_error ( EINFO_ENOMEM_RX_DATA )
#define EINFO_ENOMEM_RX_DATA
#define ENOMEM_RX_CONCAT   __einfo_error ( EINFO_ENOMEM_RX_CONCAT )
#define EINFO_ENOMEM_RX_CONCAT
#define ENOTSUP_CIPHER   __einfo_error ( EINFO_ENOTSUP_CIPHER )
#define EINFO_ENOTSUP_CIPHER
#define ENOTSUP_NULL   __einfo_error ( EINFO_ENOTSUP_NULL )
#define EINFO_ENOTSUP_NULL
#define ENOTSUP_SIG_HASH   __einfo_error ( EINFO_ENOTSUP_SIG_HASH )
#define EINFO_ENOTSUP_SIG_HASH
#define ENOTSUP_VERSION   __einfo_error ( EINFO_ENOTSUP_VERSION )
#define EINFO_ENOTSUP_VERSION
#define ENOTSUP_GROUP   __einfo_error ( EINFO_ENOTSUP_GROUP )
#define EINFO_ENOTSUP_GROUP
#define EPERM_ALERT   __einfo_error ( EINFO_EPERM_ALERT )
#define EINFO_EPERM_ALERT
#define EPERM_VERIFY   __einfo_error ( EINFO_EPERM_VERIFY )
#define EINFO_EPERM_VERIFY
#define EPERM_RENEG_INSECURE   __einfo_error ( EINFO_EPERM_RENEG_INSECURE )
#define EINFO_EPERM_RENEG_INSECURE
#define EPERM_RENEG_VERIFY   __einfo_error ( EINFO_EPERM_RENEG_VERIFY )
#define EINFO_EPERM_RENEG_VERIFY
#define EPERM_KEY_EXCHANGE   __einfo_error ( EINFO_EPERM_KEY_EXCHANGE )
#define EINFO_EPERM_KEY_EXCHANGE
#define EPERM_SAVE   __einfo_error ( EINFO_EPERM_SAVE )
#define EINFO_EPERM_SAVE
#define EPERM_DOWNGRADE   __einfo_error ( EINFO_EPERM_DOWNGRADE )
#define EINFO_EPERM_DOWNGRADE
#define EPERM_SESSION_ID   __einfo_error ( EINFO_EPERM_SESSION_ID )
#define EINFO_EPERM_SESSION_ID
#define EPROTO_VERSION   __einfo_error ( EINFO_EPROTO_VERSION )
#define EINFO_EPROTO_VERSION
#define EPROTO_CIPHER_CHANGE   __einfo_error ( EINFO_EPROTO_CIPHER_CHANGE )
#define EINFO_EPROTO_CIPHER_CHANGE
#define EPROTO_VALIDATION   __einfo_error ( EINFO_EPROTO_VALIDATION )
#define EINFO_EPROTO_VALIDATION
#define EPROTO_RETRY   __einfo_error ( EINFO_EPROTO_RETRY )
#define EINFO_EPROTO_RETRY
#define TLS_NUM_VERSIONS   ( TLS_VERSION_MAX - TLS_VERSION_MIN + 1 )
 Number of supported TLS versions.
#define TLS_LEGACY_VERSION_MAX
 Maximum pre-TLSv1.3 version.
#define TLS_NUM_CIPHER_SUITES   table_num_entries ( TLS_CIPHER_SUITES )
 Number of supported cipher suites.
#define TLS_NUM_SIG_HASH_ALGORITHMS   table_num_entries ( TLS_SIG_HASH_ALGORITHMS )
 Number of supported signature and hash algorithms.

Functions

 FILE_LICENCE (GPL2_OR_LATER)
 FILE_SECBOOT (PERMITTED)
static LIST_HEAD (tls_sessions)
 List of TLS session.
static void tls_tx_resume_all (struct tls_session *session)
 Resume TX state machine for all connections within a session.
static struct io_buffer * tls_alloc_iob (struct tls_connection *tls, size_t len)
 Allocate I/O buffer for transmitted record(s).
static int tls_send_alert (struct tls_connection *tls, unsigned int level, unsigned int description)
 Transmit Alert record.
static int tls_send_record (struct tls_connection *tls, unsigned int type, struct io_buffer *iobuf)
 Send plaintext record(s).
static int tls_send_plaintext (struct tls_connection *tls, unsigned int type, const void *data, size_t len)
 Send plaintext record.
static void tls_clear_digest (struct tls_connection *tls)
 Clear key schedule digest algorithm.
static void tls_clear_cipher (struct tls_connection *tls, struct tls_cipherspec *cipherspec)
static int tls_replay_handshake (struct tls_connection *tls, struct io_buffer *iobuf)
 Add Handshake record to transcript digest (without transmitting).
static int tls_client_hello (struct tls_connection *tls, int(*action)(struct tls_connection *tls, struct io_buffer *iobuf))
 Digest or transmit Client Hello record.
static int tls_validator_start (struct tls_connection *tls)
 Start certificate validation.
static void tls_xor (void *dst, const void *src, size_t len)
 XOR data block.
static int tls_ready (struct tls_connection *tls)
 Determine if TLS connection is ready for application data.
static int tls_version (struct tls_connection *tls, unsigned int version)
 Check for TLS version.
static int tls_has_inner (struct tls_connection *tls, struct cipher_algorithm *cipher)
 Check if TLS inner plaintext is in use.
static int tls_copy (const struct tls_cursor *src, struct tls_cursor *dst)
 Duplicate content of a TLS cursor.
static const char * tls_pipe_name (struct tls_connection *tls, struct secure_pipe *pipe)
 Get pipe name (for debugging).
static void free_tls_session (struct refcnt *refcnt)
 Free TLS session.
static void free_tls (struct refcnt *refcnt)
 Free TLS connection.
static void tls_close (struct tls_connection *tls, int rc)
 Finish with TLS connection.
static void tls_close_alert (struct tls_connection *tls, int rc)
 Send closure alert and finish with TLS connection.
static void tls_nonce (struct tls_connection *tls, struct tls_random *nonce)
 Generate deterministic connection nonce.
static void tls_random (struct tls_connection *tls, void *nonce, size_t len)
 Generate random nonce.
static int tls_set_digest (struct tls_connection *tls, struct digest_algorithm *digest)
 Set key schedule digest algorithm.
static void tls_add_handshake (struct tls_connection *tls, const void *data, size_t len)
 Add handshake record to transcript digest.
static const char * tls_version_name (unsigned int version)
 Get protocol version name (for debugging).
static const char * tls_cipher_name (struct tls_cipher_suite *suite)
 Get cipher suite name (for debugging).
static struct tls_cipher_suite * tls_find_cipher_suite (unsigned int cipher_suite)
 Identify cipher suite.
static int tls_set_verify_len (struct tls_connection *tls, size_t verify_len)
 Set verification data length.
static int tls_select_cipher (struct tls_connection *tls, unsigned int version, unsigned int cipher_suite)
 Select protocol version and cipher suite.
static void tls_clear_cipher (struct tls_connection *tls __unused, struct tls_cipherspec *cipherspec)
 Clear cipher specification.
static int tls_prep_cipher (struct tls_connection *tls, struct tls_cipherspec *cipherspec, const struct tls_phase *phase)
 Prepare cipher specification for a new traffic phase.
static int tls_change_cipher (struct tls_connection *tls, struct tls_cipherspec *cipherspec, const struct tls_phase *phase)
 Change cipher specification.
static int tls_pending_cipher (struct tls_connection *tls, struct tls_cipherspec *cipherspec)
 Apply pending traffic phase change (if any).
static struct tls_signature_hash_algorithm * tls_signature_hash_algorithm (struct pubkey_algorithm *pubkey, struct digest_algorithm *digest)
 Find TLS signature and hash algorithm.
static struct tls_signature_hash_algorithm * tls_find_signature_hash (unsigned int code)
 Find TLS signature and hash algorithm.
static struct tls_named_group * tls_find_named_group (unsigned int named_group)
 Identify named key exchange group.
static struct tls_named_group * tls_find_param_group (const struct tls_cursor *dh_p, const struct tls_cursor *dh_g)
 Identify named key exchange group by Diffie-Hellman parameters.
static int tls_parse_null (struct tls_connection *tls, const struct tls_cursor *cursor, struct tls_key_exchange_parameters *kex __unused)
 Parse key exchange parameters from unexpected Server Key Exchange record.
static int tls_parse_dhe (struct tls_connection *tls, const struct tls_cursor *cursor, struct tls_key_exchange_parameters *kex)
 Parse key exchange parameters from DHE Server Key Exchange record.
static int tls_parse_ecdhe (struct tls_connection *tls, const struct tls_cursor *cursor, struct tls_key_exchange_parameters *kex)
 Parse key exchange parameters from ECDHE Server Key Exchange record.
static int tls_keysize_is_variable (struct tls_connection *tls, struct exchange_algorithm *exchange)
 Check if key exchange keys have a variable size.
static int tls_key_share (struct tls_connection *tls, struct tls_named_group *group, struct tls_cursor *public)
 Share public key.
static int tls_key_agree (struct tls_connection *tls, struct tls_named_group *group, const struct tls_cursor *partner)
 Agree shared secret.
static int tls_key_encrypt (struct tls_connection *tls, struct tls_named_group *group, struct asn1_builder *builder)
 Encrypt (and implicitly bind) shared secret.
static int tls_hash_sign (struct tls_connection *tls, struct tls_signature_hash_algorithm *sig_hash, struct x509_certificate *cert, struct asn1_builder *sig)
 Create signature over parameters used to construct shared secret.
static int tls_hash_verify (struct tls_connection *tls, struct tls_signature_hash_algorithm *sig_hash, struct x509_certificate *cert, const struct tls_cursor *params, const struct asn1_cursor *sig)
 Verify signature over parameters used to construct shared secret.
static void tls_channel_reset (struct secure_channel *channel)
 Reset the key schedule.
static int tls_channel_apply (struct secure_channel *channel, struct exchange_algorithm *exchange, const void *shared, int *accumulated)
 Apply a new shared secret to key schedule.
static int tls_channel_save (struct secure_channel *channel, struct secure_preshared_identity *psid)
 Save a pre-shared key for future resumption of the key schedule.
static int tls_channel_load (struct secure_channel *channel, struct secure_preshared_identity *psid)
 Load a pre-shared key and resume the key schedule.
static int tls_channel_verify (struct secure_channel *channel, const void *auth, size_t len)
 Verify authenticator value.
static void tls_set_session_id (struct tls_connection *tls)
 Set a random session ID.
static int tls_session (struct tls_connection *tls, const char *name)
 Find or create session for TLS connection.
static int tls_save (struct tls_connection *tls)
 Save session for future resumption.
static int tls_resume (struct tls_connection *tls)
 Resume session.
static void tls_tx_resume (struct tls_connection *tls)
 Resume TX state machine.
static void tls_restart (struct tls_connection *tls)
 Restart negotiation.
static int tls_establish (struct tls_connection *tls)
 Establish secure channel.
static struct io_buffer * tls_alloc_handshake (struct tls_connection *tls, struct tls_cursor *cursor, unsigned int type)
 Allocate Handshake record.
static int tls_send_handshake (struct tls_connection *tls, struct io_buffer *iobuf)
 Transmit Handshake record.
static int tls_send_client_hello (struct tls_connection *tls)
 Transmit Client Hello record.
static int tls_send_certificate (struct tls_connection *tls)
 Transmit Certificate record.
static int tls_send_client_key_exchange (struct tls_connection *tls)
 Transmit Client Key Exchange record.
static int tls_send_certificate_verify (struct tls_connection *tls)
 Transmit Certificate Verify record.
static int tls_send_change_cipher (struct tls_connection *tls)
 Transmit Change Cipher record.
static int tls_send_finished (struct tls_connection *tls)
 Transmit Finished record.
static int tls_new_change_cipher (struct tls_connection *tls, struct io_buffer *iobuf)
 Receive new Change Cipher record.
static int tls_new_alert (struct tls_connection *tls, struct io_buffer *iobuf)
 Receive new Alert record.
static int tls_new_hello_request (struct tls_connection *tls, const struct tls_cursor *cursor)
 Receive new Hello Request handshake record.
static int tls_new_server_hello (struct tls_connection *tls, const struct tls_cursor *cursor)
 Receive new Server Hello handshake record.
static int tls_new_session_ticket (struct tls_connection *tls, const struct tls_cursor *cursor)
 Receive New Session Ticket handshake record.
static int tls_new_certificate (struct tls_connection *tls, const struct tls_cursor *cursor)
 Receive new Certificate handshake record.
static int tls_verify_signature (struct tls_connection *tls, const struct tls_cursor *cursor, const struct tls_cursor *params)
 Verify a signature record.
static int tls_new_certificate_verify (struct tls_connection *tls, const struct tls_cursor *cursor)
 Receive new Certificate Verify handshake record.
static int tls_new_server_key_exchange (struct tls_connection *tls, const struct tls_cursor *cursor)
 Receive new Server Key Exchange handshake record.
static int tls_new_certificate_request (struct tls_connection *tls, const struct tls_cursor *cursor __unused)
 Receive new Certificate Request handshake record.
static int tls_new_server_hello_done (struct tls_connection *tls, const struct tls_cursor *cursor)
 Receive new Server Hello Done handshake record.
static int tls_new_finished (struct tls_connection *tls, const struct tls_cursor *cursor)
 Receive new Finished handshake record.
static int tls_new_handshake (struct tls_connection *tls, struct io_buffer *iobuf)
 Receive new Handshake record.
static int tls_new_unknown (struct tls_connection *tls __unused, struct io_buffer *iobuf)
 Receive new unknown record.
static int tls_new_data (struct tls_connection *tls, struct list_head *rx_data)
 Receive new data record.
static int tls_new_record (struct tls_connection *tls, unsigned int type, struct list_head *rx_data)
 Receive new record.
static void tls_hmac_init (struct tls_cipherspec *cipherspec, void *ctx, struct tls_auth_header *authhdr)
 Initialise HMAC.
static void tls_hmac_update (struct tls_cipherspec *cipherspec, void *ctx, const void *data, size_t len)
 Update HMAC.
static void tls_hmac_final (struct tls_cipherspec *cipherspec, void *ctx, void *hmac)
 Finalise HMAC.
static void tls_hmac (struct tls_cipherspec *cipherspec, struct tls_auth_header *authhdr, const void *data, size_t len, void *hmac)
 Calculate HMAC.
static void tls_hmac_list (struct tls_cipherspec *cipherspec, struct tls_auth_header *authhdr, struct list_head *list, void *hmac)
 Calculate HMAC over list of I/O buffers.
static size_t tls_iob_reserved (struct tls_connection *tls, size_t len)
 Calculate maximum additional length required for transmitted record(s).
static int tls_verify_padding (struct tls_connection *tls, struct io_buffer *iobuf)
 Verify block padding.
static int tls_extract_inner (struct tls_connection *tls, int type, struct list_head *rx_data)
 Extract inner plaintext.
static int tls_new_ciphertext (struct tls_connection *tls, struct tls_header *tlshdr, struct list_head *rx_data)
 Receive new ciphertext record.
static size_t tls_plainstream_window (struct tls_connection *tls)
 Check flow control window.
static int tls_plainstream_deliver (struct tls_connection *tls, struct io_buffer *iobuf, struct xfer_metadata *meta __unused)
 Deliver datagram as raw data.
static int tls_progress (struct tls_connection *tls, struct job_progress *progress)
 Report job progress.
static int tls_newdata_process_header (struct tls_connection *tls)
 Handle received TLS header.
static int tls_newdata_process_data (struct tls_connection *tls)
 Handle received TLS data payload.
static size_t tls_cipherstream_window (struct tls_connection *tls)
 Check flow control window.
static int tls_cipherstream_deliver (struct tls_connection *tls, struct io_buffer *iobuf, struct xfer_metadata *xfer __unused)
 Receive new ciphertext.
static void tls_validator_done (struct tls_connection *tls, int rc)
 Handle certificate validation completion.
static void tls_tx_step (struct tls_connection *tls)
 TLS TX state machine.
int add_tls (struct interface *xfer, const char *name, struct x509_root *root, struct private_key *key)
 Add TLS on an interface.
 REQUIRING_SYMBOL (add_tls)
 REQUIRE_OBJECT (config_crypto)

Variables

struct pubkey_algorithm rsa_algorithm
static const uint8_t tls_downgrade_magic [7] = TLS_SERVER_DOWNGRADE_MAGIC
 ServerHello downgrade magic value.
static const struct tls_random tls_hrr_magic
 HelloRetryRequest magic value.
struct tls_cipher_suite tls_cipher_suite_null
 Null cipher suite.
struct tls_named_group tls_null_named_group __tls_anon_named_group
 Null named group.
struct tls_key_exchange_algorithm tls_null_exchange_algorithm
 Null key exchange algorithm.
struct tls_key_exchange_algorithm tls_pubkey_exchange_algorithm
 Public key exchange algorithm.
struct tls_key_exchange_algorithm tls_dhe_exchange_algorithm
 Ephemeral Diffie-Hellman key exchange algorithm.
struct tls_key_exchange_algorithm tls_ecdhe_exchange_algorithm
 Ephemeral Elliptic Curve Diffie-Hellman key exchange algorithm.
static struct secure_channel_operations tls_channel_ops
 Secure channel operations.
static struct interface_operation tls_plainstream_ops []
 TLS plaintext stream interface operations.
static struct interface_descriptor tls_plainstream_desc
 TLS plaintext stream interface descriptor.
static struct interface_operation tls_cipherstream_ops []
 TLS ciphertext stream interface operations.
static struct interface_descriptor tls_cipherstream_desc
 TLS ciphertext stream interface descriptor.
static struct interface_operation tls_validator_ops []
 TLS certificate validator interface operations.
static struct interface_descriptor tls_validator_desc
 TLS certificate validator interface descriptor.
static struct process_descriptor tls_process_desc
 TLS TX process descriptor.

Detailed Description

Transport Layer Security Protocol.

Definition in file tls.c.

Macro Definition Documentation

◆ EINVAL_CHANGE_CIPHER

#define EINVAL_CHANGE_CIPHER   __einfo_error ( EINFO_EINVAL_CHANGE_CIPHER )

Definition at line 53 of file tls.c.

Referenced by tls_new_change_cipher().

◆ EINFO_EINVAL_CHANGE_CIPHER

#define EINFO_EINVAL_CHANGE_CIPHER
Value:
"Invalid Change Cipher record" )
#define __einfo_uniqify(einfo_base, uniq, desc)
Declare disambiguated error.
Definition errno.h:224
#define EINFO_EINVAL
Definition errno.h:473

Definition at line 54 of file tls.c.

54#define EINFO_EINVAL_CHANGE_CIPHER \
55 __einfo_uniqify ( EINFO_EINVAL, 0x01, \
56 "Invalid Change Cipher record" )

◆ EINVAL_ALERT

#define EINVAL_ALERT   __einfo_error ( EINFO_EINVAL_ALERT )

Definition at line 57 of file tls.c.

Referenced by tls_new_alert().

◆ EINFO_EINVAL_ALERT

#define EINFO_EINVAL_ALERT
Value:
"Invalid Alert record" )

Definition at line 58 of file tls.c.

58#define EINFO_EINVAL_ALERT \
59 __einfo_uniqify ( EINFO_EINVAL, 0x02, \
60 "Invalid Alert record" )

◆ EINVAL_IV

#define EINVAL_IV   __einfo_error ( EINFO_EINVAL_IV )

Definition at line 61 of file tls.c.

Referenced by tls_new_ciphertext().

◆ EINFO_EINVAL_IV

#define EINFO_EINVAL_IV
Value:
"Invalid initialisation vector" )

Definition at line 62 of file tls.c.

62#define EINFO_EINVAL_IV \
63 __einfo_uniqify ( EINFO_EINVAL, 0x0a, \
64 "Invalid initialisation vector" )

◆ EINVAL_PADDING

#define EINVAL_PADDING   __einfo_error ( EINFO_EINVAL_PADDING )

Definition at line 65 of file tls.c.

Referenced by tls_verify_padding().

◆ EINFO_EINVAL_PADDING

#define EINFO_EINVAL_PADDING
Value:
"Invalid block padding" )

Definition at line 66 of file tls.c.

66#define EINFO_EINVAL_PADDING \
67 __einfo_uniqify ( EINFO_EINVAL, 0x0b, \
68 "Invalid block padding" )

◆ EINVAL_RX_STATE

#define EINVAL_RX_STATE   __einfo_error ( EINFO_EINVAL_RX_STATE )

Definition at line 69 of file tls.c.

Referenced by tls_cipherstream_deliver().

◆ EINFO_EINVAL_RX_STATE

#define EINFO_EINVAL_RX_STATE
Value:
"Invalid receive state" )

Definition at line 70 of file tls.c.

70#define EINFO_EINVAL_RX_STATE \
71 __einfo_uniqify ( EINFO_EINVAL, 0x0c, \
72 "Invalid receive state" )

◆ EINVAL_MAC

#define EINVAL_MAC   __einfo_error ( EINFO_EINVAL_MAC )

Definition at line 73 of file tls.c.

Referenced by tls_new_ciphertext().

◆ EINFO_EINVAL_MAC

#define EINFO_EINVAL_MAC
Value:
"Invalid MAC or authentication tag" )

Definition at line 74 of file tls.c.

74#define EINFO_EINVAL_MAC \
75 __einfo_uniqify ( EINFO_EINVAL, 0x0d, \
76 "Invalid MAC or authentication tag" )

◆ EINVAL_KEY_EXCHANGE

#define EINVAL_KEY_EXCHANGE   __einfo_error ( EINFO_EINVAL_KEY_EXCHANGE )

Definition at line 77 of file tls.c.

Referenced by tls_key_agree(), tls_key_share(), and tls_parse_null().

◆ EINFO_EINVAL_KEY_EXCHANGE

#define EINFO_EINVAL_KEY_EXCHANGE
Value:
"Invalid exchanged key" )

Definition at line 78 of file tls.c.

78#define EINFO_EINVAL_KEY_EXCHANGE \
79 __einfo_uniqify ( EINFO_EINVAL, 0x0f, \
80 "Invalid exchanged key" )

◆ EINVAL_INNER

#define EINVAL_INNER   __einfo_error ( EINFO_EINVAL_INNER )

Definition at line 81 of file tls.c.

Referenced by tls_extract_inner().

◆ EINFO_EINVAL_INNER

#define EINFO_EINVAL_INNER
Value:
"Invalid inner plaintext" )

Definition at line 82 of file tls.c.

82#define EINFO_EINVAL_INNER \
83 __einfo_uniqify ( EINFO_EINVAL, 0x10, \
84 "Invalid inner plaintext" )

◆ EINVAL_BLOCK

#define EINVAL_BLOCK   __einfo_error ( EINFO_EINVAL_BLOCK )

Definition at line 85 of file tls.c.

Referenced by tls_new_ciphertext().

◆ EINFO_EINVAL_BLOCK

#define EINFO_EINVAL_BLOCK
Value:
"Invalid block cipher size" )

Definition at line 86 of file tls.c.

86#define EINFO_EINVAL_BLOCK \
87 __einfo_uniqify ( EINFO_EINVAL, 0x11, \
88 "Invalid block cipher size" )

◆ EIO_ALERT

#define EIO_ALERT   __einfo_error ( EINFO_EIO_ALERT )

Definition at line 89 of file tls.c.

Referenced by tls_new_alert().

◆ EINFO_EIO_ALERT

#define EINFO_EIO_ALERT
Value:
"Unknown alert level" )
#define EINFO_EIO
Definition errno.h:478

Definition at line 90 of file tls.c.

90#define EINFO_EIO_ALERT \
91 __einfo_uniqify ( EINFO_EIO, 0x01, \
92 "Unknown alert level" )

◆ ENOENT_CERT

#define ENOENT_CERT   __einfo_error ( EINFO_ENOENT_CERT )

◆ EINFO_ENOENT_CERT

#define EINFO_ENOENT_CERT
Value:
"Missing certificate" )
#define EINFO_ENOENT
Definition errno.h:559

Definition at line 94 of file tls.c.

94#define EINFO_ENOENT_CERT \
95 __einfo_uniqify ( EINFO_ENOENT, 0x01, \
96 "Missing certificate" )

◆ ENOENT_KEY_EXCHANGE

#define ENOENT_KEY_EXCHANGE   __einfo_error ( EINFO_ENOENT_KEY_EXCHANGE )

Definition at line 97 of file tls.c.

◆ EINFO_ENOENT_KEY_EXCHANGE

#define EINFO_ENOENT_KEY_EXCHANGE
Value:
"No key exchange algorithm selected" )

Definition at line 98 of file tls.c.

98#define EINFO_ENOENT_KEY_EXCHANGE \
99 __einfo_uniqify ( EINFO_ENOENT, 0x02, \
100 "No key exchange algorithm selected" )

◆ ENOMEM_CONTEXT

#define ENOMEM_CONTEXT   __einfo_error ( EINFO_ENOMEM_CONTEXT )

Definition at line 101 of file tls.c.

Referenced by tls_change_cipher().

◆ EINFO_ENOMEM_CONTEXT

#define EINFO_ENOMEM_CONTEXT
Value:
"Not enough space for crypto context" )
#define EINFO_ENOMEM
Definition errno.h:579

Definition at line 102 of file tls.c.

102#define EINFO_ENOMEM_CONTEXT \
103 __einfo_uniqify ( EINFO_ENOMEM, 0x01, \
104 "Not enough space for crypto context" )

◆ ENOMEM_CERTIFICATE

#define ENOMEM_CERTIFICATE   __einfo_error ( EINFO_ENOMEM_CERTIFICATE )

Definition at line 105 of file tls.c.

◆ EINFO_ENOMEM_CERTIFICATE

#define EINFO_ENOMEM_CERTIFICATE
Value:
"Not enough space for certificate" )

Definition at line 106 of file tls.c.

106#define EINFO_ENOMEM_CERTIFICATE \
107 __einfo_uniqify ( EINFO_ENOMEM, 0x02, \
108 "Not enough space for certificate" )

◆ ENOMEM_CHAIN

#define ENOMEM_CHAIN   __einfo_error ( EINFO_ENOMEM_CHAIN )

Definition at line 109 of file tls.c.

Referenced by tls_new_certificate().

◆ EINFO_ENOMEM_CHAIN

#define EINFO_ENOMEM_CHAIN
Value:
"Not enough space for certificate chain" )

Definition at line 110 of file tls.c.

110#define EINFO_ENOMEM_CHAIN \
111 __einfo_uniqify ( EINFO_ENOMEM, 0x03, \
112 "Not enough space for certificate chain" )

◆ ENOMEM_TX_PLAINTEXT

#define ENOMEM_TX_PLAINTEXT   __einfo_error ( EINFO_ENOMEM_TX_PLAINTEXT )

Definition at line 113 of file tls.c.

Referenced by tls_send_plaintext().

◆ EINFO_ENOMEM_TX_PLAINTEXT

#define EINFO_ENOMEM_TX_PLAINTEXT
Value:
"Not enough space for transmitted plaintext" )

Definition at line 114 of file tls.c.

114#define EINFO_ENOMEM_TX_PLAINTEXT \
115 __einfo_uniqify ( EINFO_ENOMEM, 0x04, \
116 "Not enough space for transmitted plaintext" )

◆ ENOMEM_TX_CIPHERTEXT

#define ENOMEM_TX_CIPHERTEXT   __einfo_error ( EINFO_ENOMEM_TX_CIPHERTEXT )

Definition at line 117 of file tls.c.

◆ EINFO_ENOMEM_TX_CIPHERTEXT

#define EINFO_ENOMEM_TX_CIPHERTEXT
Value:
"Not enough space for transmitted ciphertext" )

Definition at line 118 of file tls.c.

118#define EINFO_ENOMEM_TX_CIPHERTEXT \
119 __einfo_uniqify ( EINFO_ENOMEM, 0x05, \
120 "Not enough space for transmitted ciphertext" )

◆ ENOMEM_RX_DATA

#define ENOMEM_RX_DATA   __einfo_error ( EINFO_ENOMEM_RX_DATA )

Definition at line 121 of file tls.c.

Referenced by tls_newdata_process_header().

◆ EINFO_ENOMEM_RX_DATA

#define EINFO_ENOMEM_RX_DATA
Value:
"Not enough space for received data" )

Definition at line 122 of file tls.c.

122#define EINFO_ENOMEM_RX_DATA \
123 __einfo_uniqify ( EINFO_ENOMEM, 0x07, \
124 "Not enough space for received data" )

◆ ENOMEM_RX_CONCAT

#define ENOMEM_RX_CONCAT   __einfo_error ( EINFO_ENOMEM_RX_CONCAT )

Definition at line 125 of file tls.c.

Referenced by tls_new_record().

◆ EINFO_ENOMEM_RX_CONCAT

#define EINFO_ENOMEM_RX_CONCAT
Value:
"Not enough space to concatenate received data" )

Definition at line 126 of file tls.c.

126#define EINFO_ENOMEM_RX_CONCAT \
127 __einfo_uniqify ( EINFO_ENOMEM, 0x08, \
128 "Not enough space to concatenate received data" )

◆ ENOTSUP_CIPHER

#define ENOTSUP_CIPHER   __einfo_error ( EINFO_ENOTSUP_CIPHER )

Definition at line 129 of file tls.c.

Referenced by tls_select_cipher().

◆ EINFO_ENOTSUP_CIPHER

#define EINFO_ENOTSUP_CIPHER
Value:
"Unsupported cipher" )
#define EINFO_ENOTSUP
Definition errno.h:634

Definition at line 130 of file tls.c.

130#define EINFO_ENOTSUP_CIPHER \
131 __einfo_uniqify ( EINFO_ENOTSUP, 0x01, \
132 "Unsupported cipher" )

◆ ENOTSUP_NULL

#define ENOTSUP_NULL   __einfo_error ( EINFO_ENOTSUP_NULL )

Definition at line 133 of file tls.c.

Referenced by tls_change_cipher().

◆ EINFO_ENOTSUP_NULL

#define EINFO_ENOTSUP_NULL
Value:
"Refusing to use null cipher" )

Definition at line 134 of file tls.c.

134#define EINFO_ENOTSUP_NULL \
135 __einfo_uniqify ( EINFO_ENOTSUP, 0x02, \
136 "Refusing to use null cipher" )

◆ ENOTSUP_SIG_HASH

#define ENOTSUP_SIG_HASH   __einfo_error ( EINFO_ENOTSUP_SIG_HASH )

Definition at line 137 of file tls.c.

Referenced by tls_send_certificate_verify(), and tls_verify_signature().

◆ EINFO_ENOTSUP_SIG_HASH

#define EINFO_ENOTSUP_SIG_HASH
Value:
"Unsupported signature and hash algorithm" )

Definition at line 138 of file tls.c.

138#define EINFO_ENOTSUP_SIG_HASH \
139 __einfo_uniqify ( EINFO_ENOTSUP, 0x03, \
140 "Unsupported signature and hash algorithm" )

◆ ENOTSUP_VERSION

#define ENOTSUP_VERSION   __einfo_error ( EINFO_ENOTSUP_VERSION )

Definition at line 141 of file tls.c.

◆ EINFO_ENOTSUP_VERSION

#define EINFO_ENOTSUP_VERSION
Value:
"Unsupported protocol version" )

Definition at line 142 of file tls.c.

142#define EINFO_ENOTSUP_VERSION \
143 __einfo_uniqify ( EINFO_ENOTSUP, 0x04, \
144 "Unsupported protocol version" )

◆ ENOTSUP_GROUP

#define ENOTSUP_GROUP   __einfo_error ( EINFO_ENOTSUP_GROUP )

Definition at line 145 of file tls.c.

Referenced by tls_new_server_hello(), tls_parse_dhe(), and tls_parse_ecdhe().

◆ EINFO_ENOTSUP_GROUP

#define EINFO_ENOTSUP_GROUP
Value:
"Unsupported key exchange group" )

Definition at line 146 of file tls.c.

146#define EINFO_ENOTSUP_GROUP \
147 __einfo_uniqify ( EINFO_ENOTSUP, 0x05, \
148 "Unsupported key exchange group" )

◆ EPERM_ALERT

#define EPERM_ALERT   __einfo_error ( EINFO_EPERM_ALERT )

Definition at line 149 of file tls.c.

Referenced by tls_new_alert().

◆ EINFO_EPERM_ALERT

#define EINFO_EPERM_ALERT
Value:
"Received fatal alert" )
#define EINFO_EPERM
Definition errno.h:659

Definition at line 150 of file tls.c.

150#define EINFO_EPERM_ALERT \
151 __einfo_uniqify ( EINFO_EPERM, 0x01, \
152 "Received fatal alert" )

◆ EPERM_VERIFY

#define EPERM_VERIFY   __einfo_error ( EINFO_EPERM_VERIFY )

Definition at line 153 of file tls.c.

Referenced by tls_channel_verify().

◆ EINFO_EPERM_VERIFY

#define EINFO_EPERM_VERIFY
Value:
"Handshake verification failed" )

Definition at line 154 of file tls.c.

154#define EINFO_EPERM_VERIFY \
155 __einfo_uniqify ( EINFO_EPERM, 0x02, \
156 "Handshake verification failed" )

◆ EPERM_RENEG_INSECURE

#define EPERM_RENEG_INSECURE   __einfo_error ( EINFO_EPERM_RENEG_INSECURE )

Definition at line 157 of file tls.c.

Referenced by tls_new_hello_request().

◆ EINFO_EPERM_RENEG_INSECURE

#define EINFO_EPERM_RENEG_INSECURE
Value:
"Secure renegotiation not supported" )

Definition at line 158 of file tls.c.

158#define EINFO_EPERM_RENEG_INSECURE \
159 __einfo_uniqify ( EINFO_EPERM, 0x04, \
160 "Secure renegotiation not supported" )

◆ EPERM_RENEG_VERIFY

#define EPERM_RENEG_VERIFY   __einfo_error ( EINFO_EPERM_RENEG_VERIFY )

Definition at line 161 of file tls.c.

Referenced by tls_new_server_hello().

◆ EINFO_EPERM_RENEG_VERIFY

#define EINFO_EPERM_RENEG_VERIFY
Value:
"Secure renegotiation verification failed" )

Definition at line 162 of file tls.c.

162#define EINFO_EPERM_RENEG_VERIFY \
163 __einfo_uniqify ( EINFO_EPERM, 0x05, \
164 "Secure renegotiation verification failed" )

◆ EPERM_KEY_EXCHANGE

#define EPERM_KEY_EXCHANGE   __einfo_error ( EINFO_EPERM_KEY_EXCHANGE )

Definition at line 165 of file tls.c.

Referenced by tls_hash_sign(), and tls_hash_verify().

◆ EINFO_EPERM_KEY_EXCHANGE

#define EINFO_EPERM_KEY_EXCHANGE
Value:
"Unusable server public key" )

Definition at line 166 of file tls.c.

166#define EINFO_EPERM_KEY_EXCHANGE \
167 __einfo_uniqify ( EINFO_EPERM, 0x06, \
168 "Unusable server public key" )

◆ EPERM_SAVE

#define EPERM_SAVE   __einfo_error ( EINFO_EPERM_SAVE )

Definition at line 169 of file tls.c.

Referenced by tls_channel_save().

◆ EINFO_EPERM_SAVE

#define EINFO_EPERM_SAVE
Value:
"Pre-shared key was not established" )

Definition at line 170 of file tls.c.

170#define EINFO_EPERM_SAVE \
171 __einfo_uniqify ( EINFO_EPERM, 0x07, \
172 "Pre-shared key was not established" )

◆ EPERM_DOWNGRADE

#define EPERM_DOWNGRADE   __einfo_error ( EINFO_EPERM_DOWNGRADE )

Definition at line 173 of file tls.c.

Referenced by tls_new_server_hello().

◆ EINFO_EPERM_DOWNGRADE

#define EINFO_EPERM_DOWNGRADE
Value:
"Downgrade attack detected" )

Definition at line 174 of file tls.c.

174#define EINFO_EPERM_DOWNGRADE \
175 __einfo_uniqify ( EINFO_EPERM, 0x08, \
176 "Downgrade attack detected" )

◆ EPERM_SESSION_ID

#define EPERM_SESSION_ID   __einfo_error ( EINFO_EPERM_SESSION_ID )

Definition at line 177 of file tls.c.

Referenced by tls_new_server_hello().

◆ EINFO_EPERM_SESSION_ID

#define EINFO_EPERM_SESSION_ID
Value:
"Session ID echo mismatch" )

Definition at line 178 of file tls.c.

178#define EINFO_EPERM_SESSION_ID \
179 __einfo_uniqify ( EINFO_EPERM, 0x09, \
180 "Session ID echo mismatch" )

◆ EPROTO_VERSION

#define EPROTO_VERSION   __einfo_error ( EINFO_EPROTO_VERSION )

Definition at line 181 of file tls.c.

Referenced by tls_select_cipher().

◆ EINFO_EPROTO_VERSION

#define EINFO_EPROTO_VERSION
Value:
"Illegal protocol version upgrade" )
#define EINFO_EPROTO
Definition errno.h:669

Definition at line 182 of file tls.c.

182#define EINFO_EPROTO_VERSION \
183 __einfo_uniqify ( EINFO_EPROTO, 0x01, \
184 "Illegal protocol version upgrade" )

◆ EPROTO_CIPHER_CHANGE

#define EPROTO_CIPHER_CHANGE   __einfo_error ( EINFO_EPROTO_CIPHER_CHANGE )

Definition at line 185 of file tls.c.

Referenced by tls_new_handshake(), and tls_select_cipher().

◆ EINFO_EPROTO_CIPHER_CHANGE

#define EINFO_EPROTO_CIPHER_CHANGE
Value:
"Illegal cipher change" )

Definition at line 186 of file tls.c.

186#define EINFO_EPROTO_CIPHER_CHANGE \
187 __einfo_uniqify ( EINFO_EPROTO, 0x02, \
188 "Illegal cipher change" )

◆ EPROTO_VALIDATION

#define EPROTO_VALIDATION   __einfo_error ( EINFO_EPROTO_VALIDATION )

Definition at line 189 of file tls.c.

Referenced by tls_validator_start().

◆ EINFO_EPROTO_VALIDATION

#define EINFO_EPROTO_VALIDATION
Value:
"Certificate validation already in progress" )

Definition at line 190 of file tls.c.

190#define EINFO_EPROTO_VALIDATION \
191 __einfo_uniqify ( EINFO_EPROTO, 0x04, \
192 "Certificate validation already in progress" )

◆ EPROTO_RETRY

#define EPROTO_RETRY   __einfo_error ( EINFO_EPROTO_RETRY )

Definition at line 193 of file tls.c.

Referenced by tls_new_server_hello().

◆ EINFO_EPROTO_RETRY

#define EINFO_EPROTO_RETRY
Value:
"Illegal retry request" )

Definition at line 194 of file tls.c.

194#define EINFO_EPROTO_RETRY \
195 __einfo_uniqify ( EINFO_EPROTO, 0x05, \
196 "Illegal retry request" )

◆ TLS_NUM_VERSIONS

#define TLS_NUM_VERSIONS   ( TLS_VERSION_MAX - TLS_VERSION_MIN + 1 )

Number of supported TLS versions.

Definition at line 244 of file tls.c.

Referenced by tls_client_hello().

◆ TLS_LEGACY_VERSION_MAX

#define TLS_LEGACY_VERSION_MAX
Value:
#define TLS_VERSION_MAX
Maximum TLS version.
Definition crypto.h:17
#define TLS_VERSION_TLS_1_2
TLS version 1.2.
Definition tlsfmt.h:177

Maximum pre-TLSv1.3 version.

Definition at line 247 of file tls.c.

247#define TLS_LEGACY_VERSION_MAX \
248 ( ( TLS_VERSION_MAX <= TLS_VERSION_TLS_1_2 ) ? \
249 TLS_VERSION_MAX : TLS_VERSION_TLS_1_2 )

Referenced by add_tls(), tls_client_hello(), and tls_select_cipher().

◆ TLS_NUM_CIPHER_SUITES

#define TLS_NUM_CIPHER_SUITES   table_num_entries ( TLS_CIPHER_SUITES )

Number of supported cipher suites.

Definition at line 627 of file tls.c.

Referenced by tls_client_hello().

◆ TLS_NUM_SIG_HASH_ALGORITHMS

#define TLS_NUM_SIG_HASH_ALGORITHMS   table_num_entries ( TLS_SIG_HASH_ALGORITHMS )

Number of supported signature and hash algorithms.

Definition at line 1008 of file tls.c.

1008#define TLS_NUM_SIG_HASH_ALGORITHMS \
1009 table_num_entries ( TLS_SIG_HASH_ALGORITHMS )

Referenced by tls_client_hello().

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER )

◆ FILE_SECBOOT()

FILE_SECBOOT ( PERMITTED )

◆ LIST_HEAD()

LIST_HEAD ( tls_sessions )
static

List of TLS session.

◆ tls_tx_resume_all()

void tls_tx_resume_all ( struct tls_session * session)
static

Resume TX state machine for all connections within a session.

Parameters
sessionTLS session

Definition at line 1863 of file tls.c.

1863 {
1864 struct tls_connection *tls;
1865
1867 tls_tx_resume ( tls );
1868}
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition list.h:432
A TLS connection.
Definition tls.h:478
struct tls_session * session
Session.
Definition tls.h:483
struct list_head list
List of connections within the same session.
Definition tls.h:485
struct list_head conn
List of connections.
Definition tls.h:412
static void tls_tx_resume(struct tls_connection *tls)
Resume TX state machine.
Definition tls.c:1854

References tls_session::conn, tls_connection::list, list_for_each_entry, tls_connection::session, and tls_tx_resume().

Referenced by tls_close(), and tls_establish().

◆ tls_alloc_iob()

struct io_buffer * tls_alloc_iob ( struct tls_connection * tls,
size_t len )
static

Allocate I/O buffer for transmitted record(s).

Parameters
tlsTLS connection
lenI/O buffer payload length
Return values
iobufI/O buffer

Definition at line 3618 of file tls.c.

3619 {
3620 struct io_buffer *iobuf;
3621 size_t reserve;
3622
3623 /* Calculate maximum additional length to reserve */
3624 reserve = tls_iob_reserved ( tls, len );
3625
3626 /* Allocate I/O buffer */
3627 iobuf = xfer_alloc_iob ( &tls->cipherstream, ( reserve + len ) );
3628 if ( ! iobuf )
3629 return NULL;
3630
3631 /* Reserve space */
3632 iob_reserve ( iobuf, reserve );
3633
3634 return iobuf;
3635}
#define NULL
NULL pointer (VOID *).
Definition Base.h:321
ring len
Length.
Definition dwmac.h:226
#define iob_reserve(iobuf, len)
Definition iobuf.h:132
A persistent I/O buffer.
Definition iobuf.h:98
struct interface cipherstream
Ciphertext stream.
Definition tls.h:494
static size_t tls_iob_reserved(struct tls_connection *tls, size_t len)
Calculate maximum additional length required for transmitted record(s).
Definition tls.c:3587
struct io_buffer * xfer_alloc_iob(struct interface *intf, size_t len)
Allocate I/O buffer.
Definition xfer.c:159

References tls_connection::cipherstream, iob_reserve, len, NULL, tls_iob_reserved(), and xfer_alloc_iob().

Referenced by tls_alloc_handshake(), and tls_send_plaintext().

◆ tls_send_alert()

int tls_send_alert ( struct tls_connection * tls,
unsigned int level,
unsigned int description )
static

Transmit Alert record.

Parameters
tlsTLS connection
levelAlert level
descriptionAlert description
Return values
rcReturn status code

Definition at line 2559 of file tls.c.

2560 {
2561 const struct {
2562 uint8_t level;
2563 uint8_t description;
2564 } __attribute__ (( packed )) alert = {
2565 .level = level,
2566 .description = description,
2567 };
2568
2569 /* Send record */
2570 return tls_send_plaintext ( tls, TLS_TYPE_ALERT, &alert,
2571 sizeof ( alert ) );
2572}
unsigned char uint8_t
Definition stdint.h:10
#define __attribute__(x)
Definition compiler.h:10
void alert(unsigned int row, const char *fmt,...)
Show alert message.
Definition message.c:104
static int tls_send_plaintext(struct tls_connection *tls, unsigned int type, const void *data, size_t len)
Send plaintext record.
Definition tls.c:3828
#define TLS_TYPE_ALERT
Alert content type.
Definition tls.h:81

References __attribute__, alert(), tls_send_plaintext(), and TLS_TYPE_ALERT.

Referenced by tls_close_alert().

◆ tls_send_record()

int tls_send_record ( struct tls_connection * tls,
unsigned int type,
struct io_buffer * iobuf )
static

Send plaintext record(s).

Parameters
tlsTLS connection
typeRecord type
iobufI/O buffer
Return values
rcReturn status code

Definition at line 3645 of file tls.c.

3646 {
3647 struct tls_cipherspec *cipherspec = &tls->tx.cipherspec;
3648 struct tls_cipher_suite *suite = cipherspec->suite;
3649 struct digest_algorithm *digest = suite->digest;
3650 struct secure_pipe *pipe = &tls->channel.tx;
3651 struct cipher_algorithm *cipher = pipe->cipher;
3652 struct {
3653 uint8_t fixed[suite->fixed_iv_len];
3654 uint8_t record[suite->record_iv_len];
3655 } __attribute__ (( packed )) iv;
3656 struct tls_auth_header authhdr;
3657 struct tls_header *tlshdr;
3658 uint8_t mac[digest->digestsize];
3659 const void *plaintext;
3660 const void *encrypt;
3661 void *ciphertext;
3662 uint8_t inner_type;
3663 size_t record_len;
3664 size_t encrypt_len;
3665 size_t pad_len;
3666 size_t len;
3667 int rc;
3668
3669 /* Sanity check */
3670 assert ( cipher == suite->cipher );
3671
3672 /* Record plaintext pointer and length */
3673 plaintext = iobuf->data;
3674 len = iob_len ( iobuf );
3675
3676 /* Add to handshake digest if applicable */
3677 if ( type == TLS_TYPE_HANDSHAKE )
3678 tls_add_handshake ( tls, plaintext, len );
3679
3680 /* Start constructing ciphertext at start of reserved space */
3681 iob_push ( iobuf, tls_iob_reserved ( tls, len ) );
3682 iob_unput ( iobuf, iob_len ( iobuf ) );
3683
3684 /* Determine inner type, if any */
3685 if ( tls_has_inner ( tls, cipher ) ) {
3686 inner_type = type;
3688 } else {
3689 inner_type = 0;
3690 }
3691
3692 /* Construct records */
3693 do {
3694 /* Limit length of this record (may be zero) */
3695 record_len = len;
3696 if ( record_len > TLS_TX_BUFSIZE )
3697 record_len = TLS_TX_BUFSIZE;
3698
3699 /* Construct authentication header */
3700 authhdr.seq = cpu_to_be64 ( cipherspec->seq++ );
3701 authhdr.header.type = type;
3702 authhdr.header.version = htons ( tls->legacy_version );
3703 authhdr.header.length = htons ( record_len );
3704
3705 /* Construct and set initialisation vector */
3706 memcpy ( iv.fixed, cipherspec->fixed_iv, sizeof ( iv.fixed ) );
3707 if ( suite->flags & TLS_CIPHER_FL_SEQUENTIAL_IV ) {
3708 memset ( iv.record, 0, sizeof ( iv.record ) );
3709 assert ( sizeof ( iv ) >= sizeof ( authhdr.seq ) );
3710 tls_xor ( ( ( ( void * ) &iv ) + sizeof ( iv )
3711 - sizeof ( authhdr.seq ) ),
3712 &authhdr.seq, sizeof ( authhdr.seq ) );
3713 } else {
3714 tls_random ( tls, iv.record, sizeof ( iv.record ) );
3715 }
3716 if ( ( rc = cipher_setiv ( cipher, pipe->ctx, &iv,
3717 sizeof ( iv ) ) ) != 0 ) {
3718 DBGC ( tls, "TLS %p could not set TX IV: %s\n",
3719 tls, strerror ( rc ) );
3720 goto err_setiv;
3721 }
3722
3723 /* Calculate encryption length */
3724 encrypt_len = record_len;
3725 if ( inner_type )
3726 encrypt_len += sizeof ( inner_type );
3727 encrypt_len += suite->mac_len;
3728 if ( is_block_cipher ( cipher ) ) {
3729 pad_len = ( ( ( cipher->blocksize - 1 ) &
3730 -( encrypt_len + 1 ) ) + 1 );
3731 } else {
3732 pad_len = 0;
3733 }
3734 encrypt_len += pad_len;
3735
3736 /* Add record header */
3737 tlshdr = iob_put ( iobuf, sizeof ( *tlshdr ) );
3738 tlshdr->type = type;
3739 tlshdr->version = htons ( tls->legacy_version );
3740 tlshdr->length = htons ( sizeof ( iv.record ) + encrypt_len +
3741 cipher->authsize );
3742
3743 /* Process authentication data */
3744 if ( suite->mac_len ) {
3745 tls_hmac ( cipherspec, &authhdr, plaintext,
3746 record_len, mac );
3747 }
3748 if ( is_auth_cipher ( cipher ) ) {
3749 if ( tls_version ( tls, TLS_VERSION_TLS_1_3 ) ) {
3750 authhdr.header.length = tlshdr->length;
3751 cipher_encrypt ( cipher, pipe->ctx,
3752 &authhdr.header, NULL,
3753 sizeof ( authhdr.header ) );
3754 } else {
3755 cipher_encrypt ( cipher, pipe->ctx, &authhdr,
3756 NULL, sizeof ( authhdr ) );
3757 }
3758 }
3759
3760 /* Add record initialisation vector, if applicable */
3761 memcpy ( iob_put ( iobuf, sizeof ( iv.record ) ), iv.record,
3762 sizeof ( iv.record ) );
3763
3764 /* Copy plaintext data if necessary */
3765 ciphertext = iob_put ( iobuf, record_len );
3766 assert ( ciphertext <= plaintext );
3767 if ( encrypt_len > record_len ) {
3768 memmove ( ciphertext, plaintext, record_len );
3769 encrypt = ciphertext;
3770 } else {
3771 encrypt = plaintext;
3772 }
3773
3774 /* Add inner type, if applicable */
3775 if ( inner_type ) {
3776 memcpy ( iob_put ( iobuf, sizeof ( inner_type ) ),
3777 &inner_type, sizeof ( inner_type ) );
3778 }
3779
3780 /* Add MAC, if applicable */
3781 memcpy ( iob_put ( iobuf, suite->mac_len ), mac,
3782 suite->mac_len );
3783
3784 /* Add padding, if applicable */
3785 memset ( iob_put ( iobuf, pad_len ), ( pad_len - 1 ),
3786 pad_len );
3787
3788 /* Encrypt data and append authentication tag */
3789 DBGC2 ( tls, "Sending plaintext data:\n" );
3790 DBGC2_HDA ( tls, 0, encrypt, encrypt_len );
3791 cipher_encrypt ( cipher, pipe->ctx, encrypt, ciphertext,
3792 encrypt_len );
3793 cipher_auth ( cipher, pipe->ctx,
3794 iob_put ( iobuf, cipher->authsize ) );
3795
3796 /* Move to next record */
3797 plaintext += record_len;
3798 len -= record_len;
3799
3800 } while ( len );
3801
3802 /* Send ciphertext */
3803 if ( ( rc = xfer_deliver_iob ( &tls->cipherstream,
3804 iob_disown ( iobuf ) ) ) != 0 ) {
3805 DBGC ( tls, "TLS %p could not deliver ciphertext: %s\n",
3806 tls, strerror ( rc ) );
3807 goto err_deliver;
3808 }
3809
3810 assert ( iobuf == NULL );
3811 return 0;
3812
3813 err_deliver:
3814 err_setiv:
3815 free_iob ( iobuf );
3816 return rc;
3817}
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:61
struct eltorito_descriptor_fixed fixed
Fixed portion.
Definition eltorito.h:1
uint32_t type
Operating system type.
Definition ena.h:1
uint8_t mac[ETH_ALEN]
MAC address.
Definition ena.h:13
#define DBGC2(...)
Definition compiler.h:547
#define DBGC2_HDA(...)
Definition compiler.h:548
#define DBGC(...)
Definition compiler.h:530
#define htons(value)
Definition byteswap.h:136
#define cpu_to_be64(value)
Definition byteswap.h:112
static int is_block_cipher(struct cipher_algorithm *cipher)
Definition crypto.h:352
static int cipher_setiv(struct cipher_algorithm *cipher, void *ctx, const void *iv, size_t ivlen)
Definition crypto.h:316
static int is_auth_cipher(struct cipher_algorithm *cipher)
Definition crypto.h:357
#define cipher_encrypt(cipher, ctx, src, dst, len)
Definition crypto.h:326
static void cipher_auth(struct cipher_algorithm *cipher, void *ctx, void *auth)
Definition crypto.h:342
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void * memset(void *dest, int character, size_t len) __nonnull
void * memmove(void *dest, const void *src, size_t len) __nonnull
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition iobuf.c:153
#define iob_push(iobuf, len)
Definition iobuf.h:149
#define iob_put(iobuf, len)
Definition iobuf.h:185
#define iob_disown(iobuf)
Disown an I/O buffer.
Definition iobuf.h:277
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition iobuf.h:220
#define iob_unput(iobuf, len)
Definition iobuf.h:200
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
A cipher algorithm.
Definition crypto.h:58
size_t blocksize
Block size.
Definition crypto.h:68
size_t authsize
Authentication tag size.
Definition crypto.h:82
A message digest algorithm.
Definition crypto.h:19
size_t digestsize
Digest size.
Definition crypto.h:27
void * data
Start of data.
Definition iobuf.h:113
struct secure_pipe tx
Transmit pipe.
Definition channel.h:82
A secure channel transmit or receive pipe.
Definition channel.h:56
void * ctx
Cipher context.
Definition channel.h:60
struct cipher_algorithm * cipher
Cipher algorithm.
Definition channel.h:58
TLS authentication header.
Definition tls.h:204
A TLS cipher suite.
Definition tls.h:266
uint8_t fixed_iv_len
Fixed initialisation vector length.
Definition tls.h:282
struct cipher_algorithm * cipher
Bulk encryption cipher algorithm.
Definition tls.h:272
uint8_t mac_len
MAC length.
Definition tls.h:286
uint8_t record_iv_len
Record initialisation vector length.
Definition tls.h:284
uint8_t flags
Flags.
Definition tls.h:290
struct digest_algorithm * digest
MAC digest algorithm.
Definition tls.h:274
A TLS cipher specification.
Definition tls.h:333
void * fixed_iv
Fixed initialisation vector.
Definition tls.h:352
uint64_t seq
Sequence number.
Definition tls.h:343
struct tls_cipher_suite * suite
Cipher suite.
Definition tls.h:335
struct secure_channel channel
Secure channel.
Definition tls.h:514
struct tls_tx tx
Transmit state.
Definition tls.h:518
uint16_t legacy_version
Legacy protocol version.
Definition tls.h:499
A TLS header.
Definition tls.h:30
uint16_t version
Protocol version.
Definition tls.h:40
uint16_t length
Length of payload.
Definition tls.h:42
uint8_t type
Content type.
Definition tls.h:35
struct tls_cipherspec cipherspec
Cipher specification.
Definition tls.h:430
static int tls_has_inner(struct tls_connection *tls, struct cipher_algorithm *cipher)
Check if TLS inner plaintext is in use.
Definition tls.c:305
static int tls_version(struct tls_connection *tls, unsigned int version)
Check for TLS version.
Definition tls.c:290
static void tls_random(struct tls_connection *tls, void *nonce, size_t len)
Generate random nonce.
Definition tls.c:527
static void tls_add_handshake(struct tls_connection *tls, const void *data, size_t len)
Add handshake record to transcript digest.
Definition tls.c:603
static void tls_hmac(struct tls_cipherspec *cipherspec, struct tls_auth_header *authhdr, const void *data, size_t len, void *hmac)
Calculate HMAC.
Definition tls.c:3546
static void tls_xor(void *dst, const void *src, size_t len)
XOR data block.
Definition tls.c:258
#define TLS_TX_BUFSIZE
TX maximum fragment length.
Definition tls.h:536
#define TLS_TYPE_HANDSHAKE
Handshake content type.
Definition tls.h:84
#define TLS_TYPE_DATA
Application data content type.
Definition tls.h:87
#define TLS_CIPHER_FL_SEQUENTIAL_IV
Cipher XORs sequence number into the initialisation vector.
Definition tls.h:294
#define TLS_VERSION_TLS_1_3
TLS version 1.3.
Definition tlsfmt.h:180
u8 iv[16]
Initialization vector.
Definition wpa.h:33
int xfer_deliver_iob(struct interface *intf, struct io_buffer *iobuf)
Deliver datagram as I/O buffer without metadata.
Definition xfer.c:256

References __attribute__, assert, cipher_algorithm::authsize, cipher_algorithm::blocksize, tls_connection::channel, secure_pipe::cipher, tls_cipher_suite::cipher, cipher_auth(), cipher_encrypt, cipher_setiv(), tls_tx::cipherspec, tls_connection::cipherstream, cpu_to_be64, secure_pipe::ctx, io_buffer::data, DBGC, DBGC2, DBGC2_HDA, tls_cipher_suite::digest, digest_algorithm::digestsize, fixed, tls_cipherspec::fixed_iv, tls_cipher_suite::fixed_iv_len, tls_cipher_suite::flags, free_iob(), tls_auth_header::header, htons, iob_disown, iob_len(), iob_push, iob_put, iob_unput, is_auth_cipher(), is_block_cipher(), iv, tls_connection::legacy_version, len, tls_header::length, mac, tls_cipher_suite::mac_len, memcpy(), memmove(), memset(), NULL, rc, tls_cipher_suite::record_iv_len, tls_auth_header::seq, tls_cipherspec::seq, strerror(), tls_cipherspec::suite, tls_add_handshake(), TLS_CIPHER_FL_SEQUENTIAL_IV, tls_has_inner(), tls_hmac(), tls_iob_reserved(), tls_random(), TLS_TX_BUFSIZE, TLS_TYPE_DATA, TLS_TYPE_HANDSHAKE, tls_version(), TLS_VERSION_TLS_1_3, tls_xor(), secure_channel::tx, tls_connection::tx, tls_header::type, type, tls_header::version, and xfer_deliver_iob().

Referenced by tls_plainstream_deliver(), tls_send_handshake(), and tls_send_plaintext().

◆ tls_send_plaintext()

int tls_send_plaintext ( struct tls_connection * tls,
unsigned int type,
const void * data,
size_t len )
static

Send plaintext record.

Parameters
tlsTLS connection
typeRecord type
dataPlaintext record
lenLength of plaintext record
Return values
rcReturn status code

Definition at line 3828 of file tls.c.

3829 {
3830 struct io_buffer *iobuf;
3831 int rc;
3832
3833 /* Allocate I/O buffer */
3834 iobuf = tls_alloc_iob ( tls, len );
3835 if ( ! iobuf )
3836 return -ENOMEM_TX_PLAINTEXT;
3837 memcpy ( iob_put ( iobuf, len ), data, len );
3838
3839 /* Transmit I/O buffer */
3840 if ( ( rc = tls_send_record ( tls, type, iob_disown ( iobuf ) ) ) != 0 )
3841 return rc;
3842
3843 return 0;
3844}
uint8_t data[48]
Additional event data.
Definition ena.h:11
static struct io_buffer * tls_alloc_iob(struct tls_connection *tls, size_t len)
Allocate I/O buffer for transmitted record(s).
Definition tls.c:3618
static int tls_send_record(struct tls_connection *tls, unsigned int type, struct io_buffer *iobuf)
Send plaintext record(s).
Definition tls.c:3645
#define ENOMEM_TX_PLAINTEXT
Definition tls.c:113

References data, ENOMEM_TX_PLAINTEXT, iob_disown, iob_put, len, memcpy(), rc, tls_alloc_iob(), tls_send_record(), and type.

Referenced by tls_send_alert(), and tls_send_change_cipher().

◆ tls_clear_digest()

void tls_clear_digest ( struct tls_connection * tls)
static

Clear key schedule digest algorithm.

Parameters
tlsTLS connection

Definition at line 549 of file tls.c.

549 {
550
551 /* Inform secure channel that key material is being destroyed */
552 channel_unkey ( &tls->channel );
553
554 /* Stop key schedule */
555 tlskey_stop ( &tls->key );
556}
void channel_unkey(struct secure_channel *channel)
Clear shared secret.
Definition channel.c:273
struct tls_key_schedule key
Key schedule.
Definition tls.h:516
void tlskey_stop(struct tls_key_schedule *tlskey)
Stop key schedule.
Definition tlskey.c:259

References tls_connection::channel, channel_unkey(), tls_connection::key, and tlskey_stop().

Referenced by add_tls(), free_tls(), and tls_set_digest().

◆ tls_clear_cipher() [1/2]

void tls_clear_cipher ( struct tls_connection * tls,
struct tls_cipherspec * cipherspec )
static

Referenced by free_tls(), and tls_change_cipher().

◆ tls_replay_handshake()

int tls_replay_handshake ( struct tls_connection * tls,
struct io_buffer * iobuf )
static

Add Handshake record to transcript digest (without transmitting).

Parameters
tlsTLS connection
iobufI/O buffer
Return values
rcReturn status code

Definition at line 1988 of file tls.c.

1989 {
1990
1991 /* Add to transcript digest */
1992 tls_add_handshake ( tls, iobuf->data, iob_len ( iobuf ) );
1993
1994 /* Free I/O buffer */
1995 free_iob ( iobuf );
1996
1997 return 0;
1998}

References io_buffer::data, free_iob(), iob_len(), and tls_add_handshake().

Referenced by tls_select_cipher().

◆ tls_client_hello()

int tls_client_hello ( struct tls_connection * tls,
int(* action )(struct tls_connection *tls, struct io_buffer *iobuf) )
static

Digest or transmit Client Hello record.

Parameters
tlsTLS connection
actionAction to take on Client Hello record
Return values
rcReturn status code

Definition at line 2007 of file tls.c.

2009 {
2010 struct tls_session *session = tls->session;
2011 struct tls_signature_hash_algorithm *sighash;
2012 struct tls_cipher_suite *suite;
2013 struct tls_named_group *group;
2014 struct {
2015 struct tls_client_hello hello;
2016 struct tls_named_group_list groups;
2017 struct tls_key_share_entry key;
2018 struct tls_key_share_client_hello keys;
2019 struct tls_server_name name;
2020 struct tls_server_name_list names;
2021 struct tls_renegotiation_info reneg;
2022 struct tls_signature_scheme_list sigs;
2023 struct tls_supported_versions supvers;
2024 } s;
2025 struct tls_client_hello *hello = &s.hello;
2026 struct tls_named_group_list *groups = &s.groups;
2027 struct tls_key_share_entry *key = &s.key;
2028 struct tls_key_share_client_hello *keys = &s.keys;
2029 struct tls_server_name *name = &s.name;
2030 struct tls_server_name_list *names = &s.names;
2031 struct tls_renegotiation_info *reneg = &s.reneg;
2032 struct tls_signature_scheme_list *sigs = &s.sigs;
2033 struct tls_supported_versions *supvers = &s.supvers;
2034 typeof ( hello->ext ) *ext = &hello->ext;
2035 struct tls_cursor cursor;
2036 struct io_buffer *iobuf;
2037 uint16_t *code;
2038 uint8_t *compression;
2039 uint8_t *frag;
2040 uint8_t empty[0];
2041 unsigned int version;
2042 unsigned int i;
2043 int rc;
2044
2045 /* Initialise data structures */
2046 memset ( &s, 0, sizeof ( s ) );
2047 version = tls->version;
2048
2049 /* Prepare ServerNameList extension */
2050 name->name.data = ( ( void * ) session->name );
2051 name->name.len = strlen ( session->name );
2052 tls_size ( tls_server_name, version, name, &names->list );
2053 tls_size ( tls_server_name_list, version, names, &ext->names );
2054
2055 /* Prepare SupportedVersions extension */
2056 supvers->list.len = ( TLS_NUM_VERSIONS * sizeof ( *code ) );
2057 tls_size ( tls_supported_versions, version, supvers, &ext->supvers );
2058
2059 /* Prepare SignatureSchemeList extension */
2060 sigs->list.len = ( TLS_NUM_SIG_HASH_ALGORITHMS * sizeof ( *code ) );
2061 tls_size ( tls_signature_scheme_list, version, sigs, &ext->sigs );
2062
2063 /* Prepare NamedGroupList extension */
2064 groups->list.len = ( TLS_NUM_NAMED_GROUPS * sizeof ( *code ) );
2065 tls_size ( tls_named_group_list, version, groups, &ext->groups );
2066 if ( ! groups->list.len )
2067 ext->groups.len = 0;
2068
2069 /* Prepare ExtendedMasterSecret extension */
2070 ext->ems.data = empty;
2071
2072 /* Prepare MaxFragmentLength extension */
2073 ext->frag.len = sizeof ( *frag );
2074
2075 /* Prepare Cookie extension */
2076 ext->cookie.data = tls->cookie.data;
2077 ext->cookie.len = tls->cookie.len;
2078
2079 /* Prepare RenegotiationInfo extension */
2080 reneg->verify.data = tls->verify.client;
2081 reneg->verify.len = tls->verify.len;
2082 if ( ! tls->secure_renegotiation )
2083 reneg->verify.len = 0;
2084 tls_size ( tls_renegotiation_info, version, reneg, &ext->reneg );
2085
2086 /* Prepare SessionTicket extension */
2087 ext->ticket.data = session->ticket.data;
2088 ext->ticket.len = session->ticket.len;
2089 if ( ! session->ticket.len )
2090 ext->ticket.data = empty;
2091
2092 /* Prepare KeyShareClientHello extension */
2093 key->group = &tls->group->code;
2094 key->public.len = tls->group->exchange->pubsize;
2096 if ( ! key->public.len )
2097 keys->list.len = 0;
2099
2100 /* Prepare ClientHello structure */
2101 hello->session_id.data = session->id.data;
2102 hello->session_id.len = session->id.len;
2103 hello->suites.len = ( TLS_NUM_CIPHER_SUITES * sizeof ( *code ) );
2104 hello->compression.len = sizeof ( *compression );
2106 &cursor ) ) != 0 ) {
2107 DBGC ( tls, "TLS %p could not size ClientHello: %s\n",
2108 tls, strerror ( rc ) );
2109 goto err_size;
2110 }
2111
2112 /* Allocate I/O buffer */
2113 iobuf = tls_alloc_handshake ( tls, &cursor, TLS_CLIENT_HELLO );
2114 if ( ! iobuf ) {
2115 rc = -ENOMEM;
2116 goto err_alloc;
2117 }
2118
2119 /* Build ClientHello structure */
2120 tls_build ( tls_client_hello, version, hello, &cursor );
2121 hello->a->version = htons ( TLS_LEGACY_VERSION_MAX );
2122 tls_nonce ( tls, ( ( struct tls_random * ) hello->a->random ) );
2123 code = hello->suites.data;
2124 i = 0 ; for_each_table_entry ( suite, TLS_CIPHER_SUITES )
2125 code[i++] = suite->code;
2126
2127 /* Build ServerNameList extension */
2128 tls_build ( tls_server_name_list, version, names, &ext->names );
2129 tls_build ( tls_server_name, version, name, &names->list );
2130
2131 /* Build SupportedVersions extension */
2132 tls_build ( tls_supported_versions, version, supvers, &ext->supvers );
2133 code = supvers->list.data;
2134 for ( i = 0 ; i < TLS_NUM_VERSIONS ; i++ )
2135 code[i] = htons ( TLS_VERSION_MAX - i );
2136
2137 /* Build SignatureSchemeList extension */
2139 code = sigs->list.data;
2141 code[i++] = sighash->code;
2142
2143 /* Build NamedGroupList extension */
2144 if ( ext->groups.len ) {
2146 &ext->groups );
2147 code = groups->list.data;
2149 if ( group->code )
2150 code[i++] = group->code;
2151 }
2153 }
2154
2155 /* Build MaxFragmentLength extension */
2156 frag = ext->frag.data;
2158
2159 /* Build RenegotiationInfo extension */
2160 tls_build ( tls_renegotiation_info, version, reneg, &ext->reneg );
2161
2162 /* Build KeyShareClientHello extension */
2164 if ( keys->list.len ) {
2166 if ( ( rc = tls_key_share ( tls, tls->group,
2167 &key->public ) ) != 0 ) {
2168 goto err_key;
2169 }
2170 }
2171
2172 /* Transmit (or digest) record */
2173 if ( ( rc = action ( tls, iob_disown ( iobuf ) ) ) != 0 )
2174 goto err_action;
2175
2176 err_action:
2177 err_key:
2178 free_iob ( iobuf );
2179 err_alloc:
2180 err_size:
2181 return rc;
2182}
union @162305117151260234136356364136041353210355154177 key
typeof(acpi_finder=acpi_find)
ACPI table finder.
Definition acpi.c:48
static unsigned int code
Definition hyperv.h:26
unsigned short uint16_t
Definition stdint.h:11
u32 version
Driver version.
Definition ath9k_hw.c:1985
const char * name
Definition ath9k_hw.c:1986
uint16_t ext
Extended status.
Definition ena.h:9
uint16_t group
Type of event.
Definition ena.h:1
#define ENOMEM
Not enough space.
Definition errno.h:578
uint16_t hello
Hello time.
Definition stp.h:27
size_t strlen(const char *src)
Get length of string.
Definition string.c:244
size_t pubsize
Public key size.
Definition crypto.h:216
uint16_t code
Numeric code (in network-endian order).
Definition tls.h:278
ClientHello descriptor.
Definition tlsfmt.h:413
struct tls_named_group * group
Key exchange named group.
Definition tls.h:503
struct tls_verify_data verify
Verification data.
Definition tls.h:509
struct tls_cursor cookie
Cookie.
Definition tls.h:511
uint16_t version
Protocol version.
Definition tls.h:497
int secure_renegotiation
Secure renegotiation flag.
Definition tls.h:505
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
KeyShareClientHello descriptor.
Definition tlsfmt.h:512
struct tls_cursor list
Key share list.
Definition tlsfmt.h:514
KeyShareEntry descriptor.
Definition tlsfmt.h:518
NamedGroupList descriptor.
Definition tlsfmt.h:560
struct tls_cursor list
Named group list.
Definition tlsfmt.h:562
A TLS named group.
Definition tls.h:308
uint16_t code
Numeric code (in network-endian order).
Definition tls.h:312
struct exchange_algorithm * exchange
Key exchange algorithm.
Definition tls.h:310
TLS client or server random bytes.
Definition tlskey.h:36
RenegotiationInfo descriptor.
Definition tlsfmt.h:589
struct tls_cursor verify
Verification data from previous Finished.
Definition tlsfmt.h:591
ServerNameList descriptor.
Definition tlsfmt.h:668
struct tls_cursor list
Server name list.
Definition tlsfmt.h:670
ServerName descriptor.
Definition tlsfmt.h:660
uint8_t len
Length of ID.
Definition tls.h:385
uint8_t data[32]
ID.
Definition tls.h:383
A TLS session.
Definition tls.h:389
struct tls_cursor ticket
Session ticket.
Definition tls.h:409
const char * name
Server name.
Definition tls.h:396
struct tls_session_id id
Session ID.
Definition tls.h:407
A TLS signature algorithm.
Definition tls.h:356
uint16_t code
Numeric code (in network-endian order).
Definition tls.h:364
SignatureSchemeList descriptor.
Definition tlsfmt.h:674
struct tls_cursor list
Supported signature algorithm list.
Definition tlsfmt.h:676
SupportedVersions descriptor (in ClientHello).
Definition tlsfmt.h:686
struct tls_cursor list
Supported version list.
Definition tlsfmt.h:688
void * client
Client verification data.
Definition tls.h:420
size_t len
Length of each verification data.
Definition tls.h:424
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
Definition tables.h:386
static int tls_key_share(struct tls_connection *tls, struct tls_named_group *group, struct tls_cursor *public)
Share public key.
Definition tls.c:1286
static struct io_buffer * tls_alloc_handshake(struct tls_connection *tls, struct tls_cursor *cursor, unsigned int type)
Allocate Handshake record.
Definition tls.c:1939
#define TLS_NUM_CIPHER_SUITES
Number of supported cipher suites.
Definition tls.c:627
#define TLS_NUM_VERSIONS
Number of supported TLS versions.
Definition tls.c:244
static void tls_nonce(struct tls_connection *tls, struct tls_random *nonce)
Generate deterministic connection nonce.
Definition tls.c:511
static int tls_client_hello(struct tls_connection *tls, int(*action)(struct tls_connection *tls, struct io_buffer *iobuf))
Digest or transmit Client Hello record.
Definition tls.c:2007
#define TLS_LEGACY_VERSION_MAX
Maximum pre-TLSv1.3 version.
Definition tls.c:247
#define TLS_NUM_SIG_HASH_ALGORITHMS
Number of supported signature and hash algorithms.
Definition tls.c:1008
#define TLS_NUM_NAMED_GROUPS
Number of non-anonymous TLS named groups.
Definition tls.h:327
#define TLS_CIPHER_SUITES
TLS cipher suite table.
Definition tls.h:297
#define TLS_MAX_FRAGMENT_LENGTH_VALUE
Advertised maximum fragment length.
Definition tls.h:528
#define TLS_CLIENT_HELLO
Definition tls.h:91
#define TLS_SIG_HASH_ALGORITHMS
TLS signature hash algorithm table.
Definition tls.h:372
#define TLS_NAMED_GROUPS
TLS named group table.
Definition tls.h:316
#define tls_build(type, version, desc, cursor)
Build TLS data structure.
Definition tlsfmt.h:763
#define tls_size(type, version, desc, cursor)
Calculate length of TLS data structure.
Definition tlsfmt.h:778

References assert, tls_verify_data::client, code, tls_cipher_suite::code, tls_named_group::code, tls_signature_hash_algorithm::code, tls_connection::cookie, tls_cursor::data, tls_session_id::data, DBGC, ENOMEM, tls_named_group::exchange, ext, for_each_table_entry, free_iob(), group, tls_connection::group, hello, htons, tls_session::id, iob_disown, key, tls_cursor::len, tls_session_id::len, tls_verify_data::len, tls_key_share_client_hello::list, tls_named_group_list::list, tls_server_name_list::list, tls_signature_scheme_list::list, tls_supported_versions::list, memset(), name, tls_session::name, exchange_algorithm::pubsize, rc, tls_connection::secure_renegotiation, tls_connection::session, strerror(), strlen(), tls_session::ticket, tls_alloc_handshake(), tls_build, TLS_CIPHER_SUITES, TLS_CLIENT_HELLO, tls_key_share(), TLS_LEGACY_VERSION_MAX, TLS_MAX_FRAGMENT_LENGTH_VALUE, TLS_NAMED_GROUPS, tls_nonce(), TLS_NUM_CIPHER_SUITES, TLS_NUM_NAMED_GROUPS, TLS_NUM_SIG_HASH_ALGORITHMS, TLS_NUM_VERSIONS, TLS_SIG_HASH_ALGORITHMS, tls_size, TLS_VERSION_MAX, typeof(), tls_connection::verify, tls_renegotiation_info::verify, tls_connection::version, and version.

Referenced by tls_send_client_hello().

◆ tls_validator_start()

int tls_validator_start ( struct tls_connection * tls)
static

Start certificate validation.

Parameters
tlsTLS connection
Return values
rcReturn status code

Definition at line 4437 of file tls.c.

4437 {
4438 int rc;
4439
4440 /* Sanity check */
4441 if ( is_pending ( &tls->server.validation ) ) {
4442 DBGC ( tls, "TLS %p refusing to restart validation\n", tls );
4443 return -EPROTO_VALIDATION;
4444 }
4445
4446 /* Begin certificate validation */
4447 if ( ( rc = create_validator ( &tls->server.validator,
4448 tls->server.chain,
4449 tls->server.root ) ) != 0 ) {
4450 DBGC ( tls, "TLS %p could not start certificate validation: "
4451 "%s\n", tls, strerror ( rc ) );
4452 return rc;
4453 }
4454 pending_get ( &tls->server.validation );
4455
4456 return 0;
4457}
void pending_get(struct pending_operation *pending)
Mark an operation as pending.
Definition pending.c:46
static int is_pending(struct pending_operation *pending)
Check if an operation is pending.
Definition pending.h:25
struct tls_server server
Server state.
Definition tls.h:524
struct pending_operation validation
Certificate validation pending operation.
Definition tls.h:472
struct interface validator
Certificate validator.
Definition tls.h:470
struct x509_root * root
Root of trust.
Definition tls.h:466
struct x509_chain * chain
Certificate chain (if any).
Definition tls.h:468
#define EPROTO_VALIDATION
Definition tls.c:189
int create_validator(struct interface *job, struct x509_chain *chain, struct x509_root *root)
Instantiate a certificate validator.
Definition validator.c:795

References tls_server::chain, create_validator(), DBGC, EPROTO_VALIDATION, is_pending(), pending_get(), rc, tls_server::root, tls_connection::server, strerror(), tls_server::validation, and tls_server::validator.

Referenced by tls_new_finished(), and tls_new_server_hello_done().

◆ tls_xor()

void tls_xor ( void * dst,
const void * src,
size_t len )
static

XOR data block.

Parameters
dstDestination data
srcSource data
lenLength of data

Definition at line 258 of file tls.c.

258 {
259 const uint8_t *src_bytes = src;
260 uint8_t *dst_bytes = dst;
261
262 while ( len-- )
263 *(dst_bytes++) ^= *(src_bytes++);
264}
static const void * src
Definition string.h:48

References len, and src.

Referenced by tls_new_ciphertext(), and tls_send_record().

◆ tls_ready()

int tls_ready ( struct tls_connection * tls)
static

Determine if TLS connection is ready for application data.

Parameters
tlsTLS connection
Return values
is_readyTLS connection is ready

Definition at line 272 of file tls.c.

272 {
273
274 return channel_is_established ( &tls->channel );
275}
static int channel_is_established(struct secure_channel *channel)
Check if secure channel has been established.
Definition channel.h:271

References tls_connection::channel, and channel_is_established().

Referenced by tls_cipherstream_window(), tls_new_data(), tls_new_hello_request(), tls_plainstream_deliver(), and tls_plainstream_window().

◆ tls_version()

int tls_version ( struct tls_connection * tls,
unsigned int version )
inlinestatic

Check for TLS version.

Parameters
tlsTLS connection
versionTLS version
Return values
at_leastTLS connection is using at least the specified version

Check that TLS connection uses at least the specified protocol version. Optimise down to a compile-time constant true result if this is already guaranteed by the minimum or maximum supported version check.

Definition at line 290 of file tls.c.

290 {
291
292 return ( ( TLS_VERSION_MAX >= version ) &&
293 ( ( TLS_VERSION_MIN >= version ) ||
294 ( tls->version >= version ) ) );
295}
#define TLS_VERSION_MIN
Minimum TLS version.
Definition crypto.h:14

References TLS_VERSION_MAX, TLS_VERSION_MIN, tls_connection::version, and version.

Referenced by tls_has_inner(), tls_keysize_is_variable(), tls_new_change_cipher(), tls_new_ciphertext(), tls_new_finished(), tls_new_server_hello(), tls_new_session_ticket(), tls_select_cipher(), tls_send_certificate_verify(), tls_send_finished(), tls_send_record(), tls_set_digest(), tls_validator_done(), and tls_verify_signature().

◆ tls_has_inner()

int tls_has_inner ( struct tls_connection * tls,
struct cipher_algorithm * cipher )
inlinestatic

Check if TLS inner plaintext is in use.

Parameters
tlsTLS connection
cipherActive cipher algorithm
Return values
has_innerInner plaintext is in use

Definition at line 305 of file tls.c.

305 {
306
307 return ( tls_version ( tls, TLS_VERSION_TLS_1_3 ) &&
308 ( cipher != &cipher_null ) );
309}
struct cipher_algorithm cipher_null
Definition crypto_null.c:94

References cipher_null, tls_version(), and TLS_VERSION_TLS_1_3.

Referenced by tls_new_ciphertext(), and tls_send_record().

◆ tls_copy()

int tls_copy ( const struct tls_cursor * src,
struct tls_cursor * dst )
static

Duplicate content of a TLS cursor.

Parameters
srcSource cursor
dstDestination cursor

The content of the source cursor (if any) will be copied.

If the source cursor is not present (e.g. because it represents an extension that was not present, rather than being present but empty) then the destination cursor will also become not present.

If the source cursor is present but empty (e.g. because it represents an extension that was present but empty) then the destination cursor will also become present but empty (with its pointer being the sentinel value as returned by malloc(0)).

If the source cursor is either empty or not present, then this function is guaranteed to succeed.

Definition at line 331 of file tls.c.

331 {
332
333 /* Free any existing content */
334 zfree ( dst->data );
335 dst->data = NULL;
336 dst->len = 0;
337
338 /* Do nothing if source cursor is not present */
339 if ( ! src->data ) {
340 assert ( src->len == 0 );
341 return 0;
342 }
343
344 /* Duplicate cursor */
345 dst->data = malloc ( src->len );
346 if ( ! dst->data )
347 return -ENOMEM;
348 memcpy ( dst->data, src->data, src->len );
349 dst->len = src->len;
350
351 return 0;
352}
void * malloc(size_t size)
Allocate memory.
Definition malloc.c:677
void zfree(void *ptr)
Clear and free memory.
Definition malloc.c:738

References assert, tls_cursor::data, ENOMEM, tls_cursor::len, malloc(), memcpy(), NULL, src, and zfree().

Referenced by tls_new_server_hello(), and tls_new_session_ticket().

◆ tls_pipe_name()

const char * tls_pipe_name ( struct tls_connection * tls,
struct secure_pipe * pipe )
static

Get pipe name (for debugging).

Parameters
tlsTLS connection
pipeSecure pipe
Return values
nameSecure pipe name

Definition at line 361 of file tls.c.

362 {
363
364 if ( pipe == &tls->channel.tx ) {
365 return "TX";
366 } else if ( pipe == &tls->channel.rx ) {
367 return "RX";
368 } else {
369 return "<UNKNOWN>";
370 }
371}
struct secure_pipe rx
Receive pipe.
Definition channel.h:84

References tls_connection::channel, secure_channel::rx, and secure_channel::tx.

Referenced by tls_change_cipher(), and tls_prep_cipher().

◆ free_tls_session()

void free_tls_session ( struct refcnt * refcnt)
static

Free TLS session.

Parameters
refcntReference counter

Definition at line 385 of file tls.c.

385 {
386 struct tls_session *session =
388
389 /* Sanity check */
390 assert ( list_empty ( &session->conn ) );
391
392 /* Remove from list of sessions */
393 list_del ( &session->list );
394
395 /* Clear pre-shared identity */
396 channel_clear_preshared ( &session->psid );
397
398 /* Free dynamically-allocated resources */
399 x509_root_put ( session->root );
400 privkey_put ( session->key );
401 zfree ( session->ticket.data );
402
403 /* Free session */
404 zfree ( session );
405}
static void channel_clear_preshared(struct secure_preshared_identity *psid)
Clear pre-shared bound peer identity.
Definition channel.h:282
#define list_del(list)
Delete an entry from a list.
Definition list.h:120
#define list_empty(list)
Test whether a list is empty.
Definition list.h:137
static void privkey_put(struct private_key *key)
Drop reference to private key.
Definition privkey.h:42
#define container_of(ptr, type, field)
Get containing structure.
Definition stddef.h:36
A reference counter.
Definition refcnt.h:27
struct private_key * key
Private key.
Definition tls.h:400
struct secure_preshared_identity psid
Bound peer identity.
Definition tls.h:403
struct x509_root * root
Root of trust.
Definition tls.h:398
struct list_head list
List of sessions.
Definition tls.h:393
static void x509_root_put(struct x509_root *root)
Drop reference to X.509 root certificate list.
Definition x509.h:404

References assert, channel_clear_preshared(), tls_session::conn, container_of, tls_cursor::data, tls_session::key, tls_session::list, list_del, list_empty, privkey_put(), tls_session::psid, tls_session::root, tls_session::ticket, x509_root_put(), and zfree().

Referenced by tls_session().

◆ free_tls()

void free_tls ( struct refcnt * refcnt)
static

Free TLS connection.

Parameters
refcntReference counter

Definition at line 412 of file tls.c.

412 {
413 struct tls_connection *tls =
415 struct tls_session *session = tls->session;
416 struct io_buffer *iobuf;
417 struct io_buffer *tmp;
418
419 /* Free dynamically-allocated resources */
420 zfree ( tls->new_ticket.data );
421 tls_clear_digest ( tls );
422 zfree ( tls->verify.dynamic );
423 zfree ( tls->cookie.data );
424 tls_clear_cipher ( tls, &tls->tx.cipherspec );
425 tls_clear_cipher ( tls, &tls->rx.cipherspec );
426 list_for_each_entry_safe ( iobuf, tmp, &tls->rx.data, list ) {
427 list_del ( &iobuf->list );
428 free_iob ( iobuf );
429 }
430 free_iob ( tls->rx.handshake );
431 privkey_put ( tls->client.key );
432 x509_chain_put ( tls->client.chain );
433 x509_chain_put ( tls->server.chain );
434 x509_root_put ( tls->server.root );
435
436 /* Drop reference to session */
437 assert ( list_empty ( &tls->list ) );
438 ref_put ( &session->refcnt );
439
440 /* Free TLS structure itself */
441 zfree ( tls );
442}
unsigned long tmp
Definition linux_pci.h:65
#define list_for_each_entry_safe(pos, tmp, head, member)
Iterate over entries in a list, safe against deletion of the current entry.
Definition list.h:459
#define ref_put(refcnt)
Drop reference to object.
Definition refcnt.h:107
struct list_head list
List of which this buffer is a member.
Definition iobuf.h:105
struct private_key * key
Private key.
Definition tls.h:456
struct x509_chain * chain
Certificate chain (if any).
Definition tls.h:458
struct tls_rx rx
Receive state.
Definition tls.h:520
struct tls_client client
Client state.
Definition tls.h:522
struct tls_cursor new_ticket
New session ticket (if any).
Definition tls.h:489
struct list_head data
List of received data buffers.
Definition tls.h:448
struct tls_cipherspec cipherspec
Cipher specification.
Definition tls.h:440
struct io_buffer * handshake
Received handshake fragment (if any).
Definition tls.h:450
struct refcnt refcnt
Reference counter.
Definition tls.h:391
void * dynamic
Dynamically allocated storage.
Definition tls.h:418
static void tls_clear_digest(struct tls_connection *tls)
Clear key schedule digest algorithm.
Definition tls.c:549
static void tls_clear_cipher(struct tls_connection *tls, struct tls_cipherspec *cipherspec)
static void x509_chain_put(struct x509_chain *chain)
Drop reference to X.509 certificate chain.
Definition x509.h:300

References assert, tls_client::chain, tls_server::chain, tls_rx::cipherspec, tls_tx::cipherspec, tls_connection::client, container_of, tls_connection::cookie, tls_cursor::data, tls_rx::data, tls_verify_data::dynamic, free_iob(), tls_rx::handshake, tls_client::key, io_buffer::list, tls_connection::list, list_del, list_empty, list_for_each_entry_safe, tls_connection::new_ticket, privkey_put(), ref_put, tls_session::refcnt, tls_server::root, tls_connection::rx, tls_connection::server, tls_connection::session, tls_clear_cipher(), tls_clear_digest(), tmp, tls_connection::tx, tls_connection::verify, x509_chain_put(), x509_root_put(), and zfree().

Referenced by add_tls().

◆ tls_close()

void tls_close ( struct tls_connection * tls,
int rc )
static

Finish with TLS connection.

Parameters
tlsTLS connection
rcStatus code

Definition at line 450 of file tls.c.

450 {
451
452 /* Remove pending operations, if applicable */
455 pending_put ( &tls->server.validation );
456
457 /* Remove process */
458 process_del ( &tls->tx.process );
459
460 /* Close all interfaces */
461 intf_shutdown ( &tls->cipherstream, rc );
462 intf_shutdown ( &tls->plainstream, rc );
463 intf_shutdown ( &tls->server.validator, rc );
464
465 /* Remove from session */
466 list_del ( &tls->list );
467 INIT_LIST_HEAD ( &tls->list );
468
469 /* Close secure channel */
470 channel_close ( &tls->channel );
471
472 /* Resume all other connections, in case we were the lead connection */
473 tls_tx_resume_all ( tls->session );
474}
void channel_close(struct secure_channel *channel)
Close secure channel.
Definition channel.c:1301
void intf_shutdown(struct interface *intf, int rc)
Shut down an object interface.
Definition interface.c:279
#define INIT_LIST_HEAD(list)
Initialise a list head.
Definition list.h:46
void pending_put(struct pending_operation *pending)
Mark an operation as no longer pending.
Definition pending.c:59
void process_del(struct process *process)
Remove process from process list.
Definition process.c:80
struct pending_operation negotiation
Security negotiation pending operation.
Definition tls.h:460
struct interface plainstream
Plaintext stream.
Definition tls.h:492
struct pending_operation negotiation
Security negotiation pending operation.
Definition tls.h:474
struct process process
Transmit process.
Definition tls.h:434
static void tls_tx_resume_all(struct tls_session *session)
Resume TX state machine for all connections within a session.
Definition tls.c:1863

References tls_connection::channel, channel_close(), tls_connection::cipherstream, tls_connection::client, INIT_LIST_HEAD, intf_shutdown(), tls_connection::list, list_del, tls_client::negotiation, tls_server::negotiation, pending_put(), tls_connection::plainstream, tls_tx::process, process_del(), rc, tls_connection::server, tls_connection::session, tls_tx_resume_all(), tls_connection::tx, tls_server::validation, and tls_server::validator.

Referenced by tls_close_alert(), and tls_new_alert().

◆ tls_close_alert()

void tls_close_alert ( struct tls_connection * tls,
int rc )
static

Send closure alert and finish with TLS connection.

Parameters
tlsTLS connection
rcStatus code

Definition at line 482 of file tls.c.

482 {
483
484 /* Send closure alert */
486
487 /* Close connection */
488 tls_close ( tls, rc );
489}
static int tls_send_alert(struct tls_connection *tls, unsigned int level, unsigned int description)
Transmit Alert record.
Definition tls.c:2559
static void tls_close(struct tls_connection *tls, int rc)
Finish with TLS connection.
Definition tls.c:450
#define TLS_ALERT_CLOSE_NOTIFY
Definition tls.h:107
#define TLS_ALERT_WARNING
Definition tls.h:103

References rc, TLS_ALERT_CLOSE_NOTIFY, TLS_ALERT_WARNING, tls_close(), and tls_send_alert().

Referenced by tls_cipherstream_deliver(), tls_tx_step(), and tls_validator_done().

◆ tls_nonce()

void tls_nonce ( struct tls_connection * tls,
struct tls_random * nonce )
static

Generate deterministic connection nonce.

Parameters
tlsTLS connection
randomConnection nonce to fill in

The nonce is guaranteed to be deterministic and to be unique for each connection (or renegotiation within a connection).

We choose to regenerate it afresh whenever the value is required (rather than generating it once and storing it) so that it is impossible to accidentally use a stale nonce.

Definition at line 511 of file tls.c.

512 {
513 static const char label[] = "tls connection nonce";
514
515 /* Generate nonce as an ephemeral secret */
517 sizeof ( *nonce ) );
518}
void channel_ephemeral_label(struct secure_channel *channel, const char *label, void *out, size_t len)
Generate labelled ephemeral secret.
Definition channel.c:215
A text label widget.
Definition label.h:16
u8 nonce[32]
Nonce value.
Definition wpa.h:25

References tls_connection::channel, channel_ephemeral_label(), and nonce.

Referenced by tls_client_hello(), and tls_set_digest().

◆ tls_random()

void tls_random ( struct tls_connection * tls,
void * nonce,
size_t len )
static

Generate random nonce.

Parameters
tlsTLS connection
nonceNonce to fill in
lenLength of nonce

Definition at line 527 of file tls.c.

528 {
529 static struct {
530 char label[16];
531 uint64_t counter;
532 } salt = {
533 .label = "tls random nonce",
534 };
535
536 /* Ensure uniqueness */
537 salt.counter++;
538
539 /* Generate nonce as an ephemeral secret */
540 channel_ephemeral ( &tls->channel, &salt, sizeof ( salt ),
541 nonce, len );
542}
unsigned long long uint64_t
Definition stdint.h:13
void channel_ephemeral(struct secure_channel *channel, const void *info, size_t info_len, void *out, size_t len)
Generate ephemeral secret.
Definition channel.c:195

References tls_connection::channel, channel_ephemeral(), len, and nonce.

Referenced by tls_send_record(), and tls_set_session_id().

◆ tls_set_digest()

int tls_set_digest ( struct tls_connection * tls,
struct digest_algorithm * digest )
static

Set key schedule digest algorithm.

Parameters
tlsTLS connection
digestKey schedule digest algorithm
Return values
rcReturn status code

Definition at line 565 of file tls.c.

566 {
567 const struct tls_key_schedule_operations *op;
568 struct tls_random nonce;
569 int rc;
570
571 /* Clear existing key schedule digest algorithm */
572 tls_clear_digest ( tls );
573
574 /* Select key schedule */
575 if ( tls_version ( tls, TLS_VERSION_TLS_1_3 ) ) {
576 op = &tlskey_hkdf;
577 } else if ( tls_version ( tls, TLS_VERSION_TLS_1_2 ) ) {
578 op = &tlskey_hash;
579 } else {
581 }
582
583 /* Generate client random bytes */
584 tls_nonce ( tls, &nonce );
585
586 /* Start key schedule */
587 if ( ( rc = tlskey_start ( &tls->key, op, digest, &nonce ) ) != 0 ) {
588 DBGC ( tls, "TLS %p could not initialise key schedule: %s\n",
589 tls, strerror ( rc ) );
590 return rc;
591 }
592
593 return 0;
594}
static uint16_t struct vmbus_xfer_pages_operations * op
Definition netvsc.h:327
TLS key schedule operations.
Definition tlskey.h:183
int tlskey_start(struct tls_key_schedule *tlskey, const struct tls_key_schedule_operations *op, struct digest_algorithm *digest, const struct tls_random *nonce)
Start key schedule.
Definition tlskey.c:180
const struct tls_key_schedule_operations tlskey_hash
TLS key schedule based on P_Hash().
Definition tlskey.c:1868
const struct tls_key_schedule_operations tlskey_md5_sha1
TLS key schedule based on P_MD5()+P_SHA1().
Definition tlskey.c:2097
const struct tls_key_schedule_operations tlskey_hkdf
TLS key schedule based on HKDF.
Definition tlskey.c:1407

References DBGC, tls_connection::key, nonce, op, rc, strerror(), tls_clear_digest(), tls_nonce(), tls_version(), TLS_VERSION_TLS_1_2, TLS_VERSION_TLS_1_3, tlskey_hash, tlskey_hkdf, tlskey_md5_sha1, and tlskey_start().

Referenced by tls_select_cipher().

◆ tls_add_handshake()

void tls_add_handshake ( struct tls_connection * tls,
const void * data,
size_t len )
static

Add handshake record to transcript digest.

Parameters
tlsTLS connection
dataHandshake record
lenLength of handshake record

Definition at line 603 of file tls.c.

604 {
605
606 /* Record in transcript digest */
607 tlskey_digest ( &tls->key, data, len );
608}
void tlskey_digest(struct tls_key_schedule *tlskey, const void *data, size_t len)
Add handshake to running transcript digest.
Definition tlskey.c:416

References data, tls_connection::key, len, and tlskey_digest().

Referenced by tls_new_handshake(), tls_replay_handshake(), and tls_send_record().

◆ tls_version_name()

const char * tls_version_name ( unsigned int version)
static

Get protocol version name (for debugging).

Parameters
versionProtocol version
Return values
nameProtocol version name

Definition at line 635 of file tls.c.

635 {
636 static char buf[ 7 /* "0xXXXX" + NUL */ ];
637
638 switch ( version ) {
639 case TLS_VERSION_TLS_1_1: return "TLSv1.1";
640 case TLS_VERSION_TLS_1_2: return "TLSv1.2";
641 case TLS_VERSION_TLS_1_3: return "TLSv1.3";
642 default:
643 snprintf ( buf, sizeof ( buf ), "%#04x", version );
644 return buf;
645 }
646}
#define TLS_VERSION_TLS_1_1
TLS version 1.1.
Definition tlsfmt.h:174
int snprintf(char *buf, size_t size, const char *fmt,...)
Write a formatted string to a buffer.
Definition vsprintf.c:383

References snprintf(), TLS_VERSION_TLS_1_1, TLS_VERSION_TLS_1_2, TLS_VERSION_TLS_1_3, and version.

Referenced by tls_select_cipher().

◆ tls_cipher_name()

const char * tls_cipher_name ( struct tls_cipher_suite * suite)
static

Get cipher suite name (for debugging).

Parameters
suiteCipher suite
Return values
nameCipher suite name

Definition at line 654 of file tls.c.

654 {
655 struct tls_key_exchange_algorithm *exchange = suite->exchange;
656 struct pubkey_algorithm *pubkey = suite->pubkey;
657 struct cipher_algorithm *cipher = suite->cipher;
658 struct digest_algorithm *digest = suite->digest;
659 struct digest_algorithm *handshake = suite->handshake;
660 const char *exchange_name;
661 const char *pubkey_name;
662 const char *digest_name;
663 static char buf[64];
664
665 /* Strip uninteresting name components */
666 exchange_name = ( ( ( exchange == &tls_null_exchange_algorithm ) ||
667 ( exchange == &tls_pubkey_exchange_algorithm ) ) ?
668 NULL : exchange->name );
669 pubkey_name = ( ( pubkey == &pubkey_null ) ? NULL : pubkey->name );
670 digest_name = ( ( digest == &digest_null ) ?
671 handshake->name : digest->name );
672
673 /* Construct name */
674 snprintf ( buf, sizeof ( buf ), "%s%s%s%s%s-%d-%s",
675 ( exchange_name ? exchange_name : "" ),
676 ( exchange_name ? "-" : "" ),
677 ( pubkey_name ? pubkey_name : "" ),
678 ( pubkey_name ? "-" : "" ),
679 cipher->name, ( suite->key_len * 8 ), digest_name );
680
681 return buf;
682}
struct pubkey_algorithm pubkey_null
struct digest_algorithm digest_null
Definition crypto_null.c:53
const char * name
Algorithm name.
Definition crypto.h:60
const char * name
Algorithm name.
Definition crypto.h:21
A public key algorithm.
Definition crypto.h:142
const char * name
Algorithm name.
Definition crypto.h:144
struct pubkey_algorithm * pubkey
Public-key encryption algorithm.
Definition tls.h:270
uint8_t key_len
Key length.
Definition tls.h:280
struct tls_key_exchange_algorithm * exchange
Key exchange algorithm.
Definition tls.h:268
struct digest_algorithm * handshake
Handshake digest algorithm (for TLSv1.2 and above).
Definition tls.h:276
A TLS key exchange algorithm.
Definition tls.h:238
const char * name
Algorithm name.
Definition tls.h:240
struct tls_key_exchange_algorithm tls_null_exchange_algorithm
Null key exchange algorithm.
Definition tls.c:1125
struct tls_key_exchange_algorithm tls_pubkey_exchange_algorithm
Public key exchange algorithm.
Definition tls.c:1138

References tls_cipher_suite::cipher, tls_cipher_suite::digest, digest_null, tls_cipher_suite::exchange, tls_cipher_suite::handshake, tls_cipher_suite::key_len, cipher_algorithm::name, digest_algorithm::name, pubkey_algorithm::name, tls_key_exchange_algorithm::name, NULL, tls_cipher_suite::pubkey, pubkey_null, snprintf(), tls_null_exchange_algorithm, and tls_pubkey_exchange_algorithm.

Referenced by tls_change_cipher(), and tls_select_cipher().

◆ tls_find_cipher_suite()

struct tls_cipher_suite * tls_find_cipher_suite ( unsigned int cipher_suite)
static

Identify cipher suite.

Parameters
cipher_suiteCipher suite specification
Return values
suiteCipher suite, or NULL

Definition at line 691 of file tls.c.

691 {
692 struct tls_cipher_suite *suite;
693
694 /* Identify cipher suite */
696 if ( suite->code == cipher_suite )
697 return suite;
698 }
699
700 return NULL;
701}

References tls_cipher_suite::code, for_each_table_entry, NULL, and TLS_CIPHER_SUITES.

Referenced by tls_select_cipher().

◆ tls_set_verify_len()

int tls_set_verify_len ( struct tls_connection * tls,
size_t verify_len )
static

Set verification data length.

Parameters
tlsTLS connection
verify_lenVerification data length
Return values
rcReturn status code

Definition at line 710 of file tls.c.

711 {
712 struct tls_verify_data *verify = &tls->verify;
713 size_t total;
714 void *dynamic;
715
716 /* Free any existing dynamically allocated storage */
717 zfree ( verify->dynamic );
718 memset ( verify, 0, sizeof ( *verify ) );
719
720 /* Allocate dynamic storage */
721 total = ( verify_len * 2 );
722 dynamic = zalloc ( total );
723 if ( ! dynamic )
724 return -ENOMEM;
725 verify->len = verify_len;
726
727 /* Assign storage */
728 verify->dynamic = dynamic;
729 verify->client = dynamic; dynamic += verify_len;
730 verify->server = dynamic; dynamic += verify_len;
731 assert ( ( verify->dynamic + total ) == dynamic );
732
733 return 0;
734}
void * zalloc(size_t size)
Allocate cleared memory.
Definition malloc.c:718
TLS verification data.
Definition tls.h:416
void * server
Server verification data.
Definition tls.h:422

References assert, tls_verify_data::client, tls_verify_data::dynamic, ENOMEM, tls_verify_data::len, memset(), tls_verify_data::server, tls_connection::verify, zalloc(), and zfree().

Referenced by tls_select_cipher().

◆ tls_select_cipher()

int tls_select_cipher ( struct tls_connection * tls,
unsigned int version,
unsigned int cipher_suite )
static

Select protocol version and cipher suite.

Parameters
tlsTLS connection
versionProtocol version
cipher_suiteCipher suite specification
Return values
rcReturn status code

Definition at line 744 of file tls.c.

746 {
747 struct tls_cipher_suite *suite;
748 struct digest_algorithm *digest;
749 int rc;
750
751 /* Check protocol version */
752 if ( version < TLS_VERSION_MIN ) {
753 DBGC ( tls, "TLS %p does not support protocol version %s\n",
754 tls, tls_version_name ( version ) );
755 return -ENOTSUP_VERSION;
756 }
757 if ( version > tls->version ) {
758 DBGC ( tls, "TLS %p refusing illegal upgrade to protocol "
759 "version %s\n", tls, tls_version_name ( version ) );
760 return -EPROTO_VERSION;
761 }
762
763 /* Identify cipher suite */
764 suite = tls_find_cipher_suite ( cipher_suite );
765 if ( ! suite ) {
766 DBGC ( tls, "TLS %p does not support cipher suite %#04x\n",
767 tls, ntohs ( cipher_suite ) );
768 return -ENOTSUP_CIPHER;
769 }
770
771 /* Sanity checks */
772 if ( ! ( suite->exchange && suite->pubkey && suite->cipher &&
773 suite->digest && suite->handshake ) ) {
774 DBGC ( tls, "TLS %p cannot use broken cipher suite %#04x\n",
775 tls, ntohs ( cipher_suite ) );
776 return -ENOTSUP_CIPHER;
777 }
778
779 /* If cipher suite is already active (e.g. due to a valid
780 * HelloRetryRequest), leave it intact.
781 */
782 if ( ( version == tls->version ) && ( suite == tls->suite ) )
783 return 0;
784
785 /* Refuse any attempt to change an active cipher suite */
786 if ( tls->suite != &tls_cipher_suite_null ) {
787 DBGC ( tls, "TLS %p refusing to change to %s %s\n",
788 tls, tls_version_name ( version ),
789 tls_cipher_name ( suite ) );
790 return -EPROTO_CIPHER_CHANGE;
791 }
792
793 /* Set protocol version */
794 tls->version = version;
795 tls->legacy_version = version;
798 DBGC ( tls, "TLS %p using protocol version %s\n",
799 tls, tls_version_name ( version ) );
800
801 /* Set key schedule digest algorithm */
802 digest = ( tls_version ( tls, TLS_VERSION_TLS_1_2 ) ?
803 suite->handshake : &md5_sha1_algorithm );
804 if ( ( rc = tls_set_digest ( tls, digest ) ) != 0 )
805 return rc;
806
807 /* Add initial Client Hello to handshake digest
808 *
809 * When the Client Hello was originally sent, the digest
810 * algorithm selected by the server's choice of cipher suite
811 * was not yet known. This is the earliest point at which it
812 * can be incorporated into the handshake transcript digest.
813 */
814 if ( ( rc = tls_client_hello ( tls, tls_replay_handshake ) ) != 0 )
815 return rc;
816
817 /* Set verification data length */
818 if ( ( rc = tls_set_verify_len ( tls, suite->verify_len ) ) != 0 )
819 return rc;
820
821 /* Set default named group */
822 tls->group = suite->exchange->group;
823
824 /* Set cipher suite */
825 tls->suite = suite;
826 DBGC ( tls, "TLS %p selected cipher suite %s\n",
827 tls, tls_cipher_name ( suite ) );
828
829 return 0;
830}
#define ntohs(value)
Definition byteswap.h:137
struct digest_algorithm md5_sha1_algorithm
Hybrid MD5+SHA1 digest algorithm.
Definition md5_sha1.c:87
#define ENOTSUP_VERSION
Definition stp.c:46
uint8_t verify_len
Verification data length.
Definition tls.h:288
struct tls_cipher_suite * suite
Cipher suite.
Definition tls.h:501
struct tls_named_group * group
Default named group.
Definition tls.h:242
#define ENOTSUP_CIPHER
Definition tls.c:129
static int tls_set_digest(struct tls_connection *tls, struct digest_algorithm *digest)
Set key schedule digest algorithm.
Definition tls.c:565
static int tls_replay_handshake(struct tls_connection *tls, struct io_buffer *iobuf)
Add Handshake record to transcript digest (without transmitting).
Definition tls.c:1988
static struct tls_cipher_suite * tls_find_cipher_suite(unsigned int cipher_suite)
Identify cipher suite.
Definition tls.c:691
static const char * tls_cipher_name(struct tls_cipher_suite *suite)
Get cipher suite name (for debugging).
Definition tls.c:654
static const char * tls_version_name(unsigned int version)
Get protocol version name (for debugging).
Definition tls.c:635
#define EPROTO_CIPHER_CHANGE
Definition tls.c:185
struct tls_cipher_suite tls_cipher_suite_null
Null cipher suite.
Definition tls.c:618
#define EPROTO_VERSION
Definition tls.c:181
static int tls_set_verify_len(struct tls_connection *tls, size_t verify_len)
Set verification data length.
Definition tls.c:710

References tls_cipher_suite::cipher, DBGC, tls_cipher_suite::digest, ENOTSUP_CIPHER, ENOTSUP_VERSION, EPROTO_CIPHER_CHANGE, EPROTO_VERSION, tls_cipher_suite::exchange, tls_connection::group, tls_key_exchange_algorithm::group, tls_cipher_suite::handshake, tls_connection::legacy_version, md5_sha1_algorithm, ntohs, tls_cipher_suite::pubkey, rc, tls_connection::suite, tls_cipher_name(), tls_cipher_suite_null, tls_find_cipher_suite(), TLS_LEGACY_VERSION_MAX, tls_replay_handshake(), tls_set_digest(), tls_set_verify_len(), tls_version(), TLS_VERSION_MIN, tls_version_name(), TLS_VERSION_TLS_1_2, tls_cipher_suite::verify_len, tls_connection::version, and version.

Referenced by tls_new_server_hello().

◆ tls_clear_cipher() [2/2]

void tls_clear_cipher ( struct tls_connection *tls __unused,
struct tls_cipherspec * cipherspec )
static

Clear cipher specification.

Parameters
tlsTLS connection
cipherspecTLS cipher specification

Definition at line 838 of file tls.c.

839 {
840
841 /* Clear cipher */
842 channel_clear_cipher ( cipherspec->pipe );
843
844 /* Reset to the null cipher suite (with no dynamic storage) */
845 cipherspec->suite = &tls_cipher_suite_null;
846
847 /* Clear and free any dynamically-allocated storage */
848 zfree ( cipherspec->dynamic );
849 cipherspec->dynamic = NULL;
850 cipherspec->cipher_key = NULL;
851 cipherspec->mac_secret = NULL;
852 cipherspec->fixed_iv = NULL;
853
854 /* Reset sequence number */
855 cipherspec->seq = 0;
856}
void channel_clear_cipher(struct secure_pipe *pipe)
Clear cipher algorithm.
Definition channel.c:1106
void * cipher_key
Cipher key.
Definition tls.h:348
void * dynamic
Dynamically-allocated storage.
Definition tls.h:346
struct secure_pipe * pipe
Secure pipe.
Definition tls.h:339
void * mac_secret
MAC secret.
Definition tls.h:350

References __unused, channel_clear_cipher(), tls_cipherspec::cipher_key, tls_cipherspec::dynamic, tls_cipherspec::fixed_iv, tls_cipherspec::mac_secret, NULL, tls_cipherspec::pipe, tls_cipherspec::seq, tls_cipherspec::suite, tls_cipher_suite_null, and zfree().

◆ tls_prep_cipher()

int tls_prep_cipher ( struct tls_connection * tls,
struct tls_cipherspec * cipherspec,
const struct tls_phase * phase )
static

Prepare cipher specification for a new traffic phase.

Parameters
tlsTLS connection
cipherspecTLS cipher specification
phaseTraffic phase
Return values
rcReturn status code

Definition at line 866 of file tls.c.

868 {
869 const struct tls_endpoint *writer = cipherspec->writer;
870 struct secure_pipe *pipe = cipherspec->pipe;
871 int rc;
872
873 /* Generate traffic secret */
874 if ( ( rc = tlskey_traffic ( &tls->key, writer, phase ) ) != 0 ) {
875 DBGC ( tls, "TLS %p could not generate %s %s traffic secret: "
876 "%s\n", tls, tls_pipe_name ( tls, pipe ),
877 writer->name, strerror ( rc ) );
878 return rc;
879 }
880
881 return 0;
882}
const struct tls_endpoint * writer
Writer endpoint.
Definition tls.h:337
A TLS endpoint.
Definition tlskey.h:19
const char name[7]
Name (for key expansion labels).
Definition tlskey.h:23
static const char * tls_pipe_name(struct tls_connection *tls, struct secure_pipe *pipe)
Get pipe name (for debugging).
Definition tls.c:361
int tlskey_traffic(struct tls_key_schedule *tlskey, const struct tls_endpoint *writer, const struct tls_phase *phase)
Generate traffic secret.
Definition tlskey.c:667

References DBGC, tls_connection::key, tls_endpoint::name, tls_cipherspec::pipe, rc, strerror(), tls_pipe_name(), tlskey_traffic(), and tls_cipherspec::writer.

Referenced by tls_change_cipher(), and tls_send_finished().

◆ tls_change_cipher()

int tls_change_cipher ( struct tls_connection * tls,
struct tls_cipherspec * cipherspec,
const struct tls_phase * phase )
static

Change cipher specification.

Parameters
tlsTLS connection
cipherspecTLS cipher specification
phaseNew traffic phase (or NULL to retain existing phase)
Return values
rcReturn status code

Definition at line 892 of file tls.c.

894 {
895 struct tls_cipher_suite *suite = tls->suite;
896 const struct tls_endpoint *writer = cipherspec->writer;
897 struct secure_pipe *pipe = cipherspec->pipe;
898 size_t total;
899 void *dynamic;
900 int rc;
901
902 /* Clear any existing cipher specification */
903 tls_clear_cipher ( tls, cipherspec );
904
905 /* Sanity check */
906 if ( suite == &tls_cipher_suite_null ) {
907 DBGC ( tls, "TLS %p refusing to use null %s cipher\n",
908 tls, tls_pipe_name ( tls, pipe ) );
909 rc = -ENOTSUP_NULL;
910 goto err_null;
911 }
912
913 /* Allocate dynamic storage */
914 total = ( suite->key_len + suite->mac_len + suite->fixed_iv_len );
915 dynamic = zalloc ( total );
916 if ( ! dynamic ) {
917 DBGC ( tls, "TLS %p could not allocate %zd bytes for crypto "
918 "context\n", tls, total );
920 goto err_alloc;
921 }
922
923 /* Assign storage */
924 cipherspec->dynamic = dynamic;
925 cipherspec->cipher_key = dynamic; dynamic += suite->key_len;
926 cipherspec->mac_secret = dynamic; dynamic += suite->mac_len;
927 cipherspec->fixed_iv = dynamic; dynamic += suite->fixed_iv_len;
928 assert ( ( cipherspec->dynamic + total ) == dynamic );
929
930 /* Record cipher suite */
931 cipherspec->suite = suite;
932
933 /* Prepare for new traffic phase, if applicable */
934 if ( phase &&
935 ( ( rc = tls_prep_cipher ( tls, cipherspec, phase ) ) != 0 ) ) {
936 goto err_prep;
937 }
938
939 /* Generate cipher key material */
940 if ( ( rc = tlskey_cipher ( &tls->key, writer,
941 cipherspec->cipher_key, suite->key_len,
942 cipherspec->fixed_iv, suite->fixed_iv_len,
943 cipherspec->mac_secret,
944 suite->mac_len ) ) != 0 ) {
945 DBGC ( tls, "TLS %p could not generate %s %s keys: %s\n",
946 tls, tls_pipe_name ( tls, pipe ), writer->name,
947 strerror ( rc ) );
948 goto err_cipher;
949 }
950
951 /* Set cipher algorithm and key */
952 if ( ( rc = channel_set_cipher ( &tls->channel, pipe, suite->cipher,
953 cipherspec->cipher_key,
954 suite->key_len ) ) != 0 ) {
955 DBGC ( tls, "TLS %p could not set %s cipher: %s\n",
956 tls, tls_pipe_name ( tls, pipe ), strerror ( rc ) );
957 goto err_channel;
958 }
959
960 DBGC ( tls, "TLS %p activated %s cipher %s\n",
961 tls, tls_pipe_name ( tls, pipe ), tls_cipher_name ( suite ) );
962 return 0;
963
964 err_channel:
965 err_cipher:
966 err_prep:
967 tls_clear_cipher ( tls, cipherspec );
968 err_alloc:
969 err_null:
970 return rc;
971}
int channel_set_cipher(struct secure_channel *channel, struct secure_pipe *pipe, struct cipher_algorithm *cipher, const void *key, size_t len)
Set cipher algorithm and key.
Definition channel.c:1136
#define ENOTSUP_NULL
Definition tls.c:133
static int tls_prep_cipher(struct tls_connection *tls, struct tls_cipherspec *cipherspec, const struct tls_phase *phase)
Prepare cipher specification for a new traffic phase.
Definition tls.c:866
#define ENOMEM_CONTEXT
Definition tls.c:101
int tlskey_cipher(struct tls_key_schedule *tlskey, const struct tls_endpoint *writer, void *key, size_t key_len, void *iv, size_t iv_len, void *mac, size_t mac_len)
Generate cipher key material.
Definition tlskey.c:719

References assert, tls_connection::channel, channel_set_cipher(), tls_cipher_suite::cipher, tls_cipherspec::cipher_key, DBGC, tls_cipherspec::dynamic, ENOMEM_CONTEXT, ENOTSUP_NULL, tls_cipherspec::fixed_iv, tls_cipher_suite::fixed_iv_len, tls_connection::key, tls_cipher_suite::key_len, tls_cipher_suite::mac_len, tls_cipherspec::mac_secret, tls_endpoint::name, tls_cipherspec::pipe, rc, strerror(), tls_cipherspec::suite, tls_connection::suite, tls_cipher_name(), tls_cipher_suite_null, tls_clear_cipher(), tls_pipe_name(), tls_prep_cipher(), tlskey_cipher(), tls_cipherspec::writer, and zalloc().

Referenced by tls_pending_cipher(), tls_send_change_cipher(), and tls_send_finished().

◆ tls_pending_cipher()

int tls_pending_cipher ( struct tls_connection * tls,
struct tls_cipherspec * cipherspec )
static

Apply pending traffic phase change (if any).

Parameters
tlsTLS connection
cipherspecTLS cipher specification
Return values
rcReturn status code

Definition at line 980 of file tls.c.

981 {
982 const struct tls_phase *pending;
983 int rc;
984
985 /* Do nothing if no change is pending */
986 pending = cipherspec->pending;
987 if ( ! pending )
988 return 0;
989
990 /* Change cipher */
991 if ( ( rc = tls_change_cipher ( tls, cipherspec, pending ) ) != 0 )
992 return rc;
993
994 /* Clear pending change */
995 cipherspec->pending = NULL;
996
997 return 0;
998}
uint32_t pending
Pending events.
Definition hyperv.h:1
const struct tls_phase * pending
Pending traffic phase change.
Definition tls.h:341
A TLS traffic phase.
Definition tlskey.c:127
static int tls_change_cipher(struct tls_connection *tls, struct tls_cipherspec *cipherspec, const struct tls_phase *phase)
Change cipher specification.
Definition tls.c:892

References NULL, pending, tls_cipherspec::pending, rc, and tls_change_cipher().

Referenced by tls_new_ciphertext().

◆ tls_signature_hash_algorithm()

struct tls_signature_hash_algorithm * tls_signature_hash_algorithm ( struct pubkey_algorithm * pubkey,
struct digest_algorithm * digest )
static

Find TLS signature and hash algorithm.

Parameters
pubkeyPublic-key algorithm
digestDigest algorithm
Return values
sig_hashSignature and hash algorithm, or NULL

Definition at line 1019 of file tls.c.

1020 {
1021 struct tls_signature_hash_algorithm *sig_hash;
1022
1023 /* Identify signature and hash algorithm */
1025 if ( ( sig_hash->pubkey == pubkey ) &&
1026 ( sig_hash->digest == digest ) ) {
1027 return sig_hash;
1028 }
1029 }
1030
1031 return NULL;
1032}
struct pubkey_algorithm * pubkey
Public-key algorithm.
Definition tls.h:360
struct digest_algorithm * digest
Digest algorithm.
Definition tls.h:358

References tls_signature_hash_algorithm::digest, for_each_table_entry, NULL, tls_signature_hash_algorithm::pubkey, and TLS_SIG_HASH_ALGORITHMS.

Referenced by tls_send_certificate_verify().

◆ tls_find_signature_hash()

struct tls_signature_hash_algorithm * tls_find_signature_hash ( unsigned int code)
static

Find TLS signature and hash algorithm.

Parameters
codeSignature and hash algorithm identifier
Return values
sig_hashSignature and hash algorithm, or NULL

Definition at line 1041 of file tls.c.

1041 {
1042 struct tls_signature_hash_algorithm *sig_hash;
1043
1044 /* Identify signature and hash algorithm */
1046 if ( sig_hash->code == code )
1047 return sig_hash;
1048 }
1049
1050 return NULL;
1051}

References code, tls_signature_hash_algorithm::code, for_each_table_entry, NULL, and TLS_SIG_HASH_ALGORITHMS.

Referenced by tls_verify_signature().

◆ tls_find_named_group()

struct tls_named_group * tls_find_named_group ( unsigned int named_group)
static

Identify named key exchange group.

Parameters
named_groupNamed group specification
Return values
groupNamed group, or NULL

Definition at line 1067 of file tls.c.

1067 {
1068 struct tls_named_group *group;
1069
1070 /* Identify named group */
1072 if ( group->code && ( group->code == named_group ) )
1073 return group;
1074 }
1075
1076 return NULL;
1077}

References for_each_table_entry, group, NULL, and TLS_NAMED_GROUPS.

Referenced by tls_new_server_hello(), and tls_parse_ecdhe().

◆ tls_find_param_group()

struct tls_named_group * tls_find_param_group ( const struct tls_cursor * dh_p,
const struct tls_cursor * dh_g )
static

Identify named key exchange group by Diffie-Hellman parameters.

Parameters
dh_pPrime modulus
dh_gGenerator
Return values
groupNamed group, or NULL

Definition at line 1087 of file tls.c.

1088 {
1089 struct tls_named_group *group;
1090
1091 /* Identify named group by parameters */
1093 if ( is_ffdhe ( group->exchange ) &&
1094 ffdhe_has_params ( group->exchange, dh_p->data,
1095 dh_p->len, dh_g->data, dh_g->len ) ) {
1096 return group;
1097 }
1098 }
1099
1100 return NULL;
1101}
int ffdhe_has_params(struct exchange_algorithm *exchange, const void *dh_p, size_t dh_p_len, const void *dh_g, size_t dh_g_len)
Check group parameters.
Definition ffdhe.c:310
static int is_ffdhe(struct exchange_algorithm *exchange)
Check if key exchange algorithm is a finite field DHE group.
Definition ffdhe.h:52

References tls_cursor::data, ffdhe_has_params(), for_each_table_entry, group, is_ffdhe(), tls_cursor::len, NULL, and TLS_NAMED_GROUPS.

Referenced by tls_parse_dhe().

◆ tls_parse_null()

int tls_parse_null ( struct tls_connection * tls,
const struct tls_cursor * cursor,
struct tls_key_exchange_parameters *kex __unused )
static

Parse key exchange parameters from unexpected Server Key Exchange record.

Parameters
cursorServer Key Exchange handshake record
kexKey exchange parameters to fill in
Return values
rcReturn status code

Definition at line 1111 of file tls.c.

1112 {
1113
1114 DBGC ( tls, "TLS %p received unexpected ServerKeyExchange:\n", tls );
1115 DBGC_HDA ( tls, 0, cursor->data, cursor->len );
1116 return -EINVAL_KEY_EXCHANGE;
1117}
#define DBGC_HDA(...)
Definition compiler.h:531
#define EINVAL_KEY_EXCHANGE
Definition tls.c:77

References __unused, tls_cursor::data, DBGC, DBGC_HDA, EINVAL_KEY_EXCHANGE, and tls_cursor::len.

◆ tls_parse_dhe()

int tls_parse_dhe ( struct tls_connection * tls,
const struct tls_cursor * cursor,
struct tls_key_exchange_parameters * kex )
static

Parse key exchange parameters from DHE Server Key Exchange record.

Parameters
tlsTLS connection
cursorServer Key Exchange handshake record
kexKey exchange parameters to fill in
Return values
rcReturn status code

Definition at line 1153 of file tls.c.

1155 {
1156 struct tls_server_key_exchange_dhe dhe;
1157 struct tls_named_group *group;
1158 int rc;
1159
1160 /* Parse ServerKeyExchange structure */
1162 cursor, &dhe ) ) != 0 ) {
1163 DBGC ( tls, "TLS %p could not parse ServerKeyExchange: %s\n",
1164 tls, strerror ( rc ) );
1165 return rc;
1166 }
1167
1168 /* Identify named group */
1169 group = tls_find_param_group ( &dhe.dh_p, &dhe.dh_g );
1170 if ( ! group ) {
1171 DBGC ( tls, "TLS %p unsupported %zd-bit group:\n",
1172 tls, ( 8 * dhe.dh_p.len ) );
1173 DBGC_HDA ( tls, 0, cursor->data, cursor->len );
1174 return -ENOTSUP_GROUP;
1175 }
1176
1177 /* Construct parameters */
1178 kex->len = ( cursor->len - dhe.dsig.len );
1179 kex->group = group;
1180 kex->partner = dhe.dh_ys;
1181
1182 return 0;
1183}
size_t len
Length of parameters (excluding trailing signature).
Definition tls.h:230
struct tls_named_group * group
Named group.
Definition tls.h:232
struct tls_cursor partner
Partner key.
Definition tls.h:234
ServerKeyExchange descriptor (for DHE).
Definition tlsfmt.h:633
#define ENOTSUP_GROUP
Definition tls.c:145
static struct tls_named_group * tls_find_param_group(const struct tls_cursor *dh_p, const struct tls_cursor *dh_g)
Identify named key exchange group by Diffie-Hellman parameters.
Definition tls.c:1087
#define tls_parse(type, version, cursor, desc)
Parse TLS data structure.
Definition tlsfmt.h:733

References tls_cursor::data, DBGC, DBGC_HDA, tls_server_key_exchange_dhe::dh_g, tls_server_key_exchange_dhe::dh_p, tls_server_key_exchange_dhe::dh_ys, tls_server_key_exchange_dhe::dsig, ENOTSUP_GROUP, group, tls_key_exchange_parameters::group, tls_cursor::len, tls_key_exchange_parameters::len, tls_key_exchange_parameters::partner, rc, strerror(), tls_find_param_group(), tls_parse, and tls_connection::version.

◆ tls_parse_ecdhe()

int tls_parse_ecdhe ( struct tls_connection * tls,
const struct tls_cursor * cursor,
struct tls_key_exchange_parameters * kex )
static

Parse key exchange parameters from ECDHE Server Key Exchange record.

Parameters
tlsTLS connection
cursorServer Key Exchange handshake record
lenLength of Server Key Exchange handshake record
kexKey exchange parameters to fill in
Return values
rcReturn status code

Definition at line 1202 of file tls.c.

1204 {
1205 struct tls_server_key_exchange_ecdhe ecdhe;
1206 struct tls_named_group *group;
1207 int rc;
1208
1209 /* Parse ServerKeyExchange structure */
1211 cursor, &ecdhe ) ) != 0 ) {
1212 DBGC ( tls, "TLS %p could not parse ServerKeyExchange: %s\n",
1213 tls, strerror ( rc ) );
1214 return rc;
1215 }
1216
1217 /* Identify named group */
1218 if ( ecdhe.curve->type != TLS_NAMED_CURVE_TYPE ) {
1219 DBGC ( tls, "TLS %p unsupported curve type %d\n",
1220 tls, ecdhe.curve->type );
1221 DBGC_HDA ( tls, 0, cursor->data, cursor->len );
1222 return -ENOTSUP_GROUP;
1223 }
1224 group = tls_find_named_group ( ecdhe.curve->group );
1225 if ( ! group ) {
1226 DBGC ( tls, "TLS %p unsupported named group %d\n",
1227 tls, ntohs ( ecdhe.curve->group ) );
1228 DBGC_HDA ( tls, 0, cursor->data, cursor->len );
1229 return -ENOTSUP_GROUP;
1230 }
1231
1232 /* Construct parameters */
1233 kex->len = ( cursor->len - ecdhe.dsig.len );
1234 kex->group = group;
1235 kex->partner = ecdhe.point;
1236
1237 return 0;
1238}
ServerKeyExchange descriptor (for ECDHE).
Definition tlsfmt.h:645
static struct tls_named_group * tls_find_named_group(unsigned int named_group)
Identify named key exchange group.
Definition tls.c:1067
#define TLS_NAMED_CURVE_TYPE
TLS named curve type.
Definition tls.h:305

References tls_server_key_exchange_ecdhe::curve, tls_cursor::data, DBGC, DBGC_HDA, tls_server_key_exchange_ecdhe::dsig, ENOTSUP_GROUP, group, tls_key_exchange_parameters::group, tls_server_key_exchange_ecdhe::group, tls_cursor::len, tls_key_exchange_parameters::len, ntohs, tls_key_exchange_parameters::partner, tls_server_key_exchange_ecdhe::point, rc, strerror(), tls_find_named_group(), TLS_NAMED_CURVE_TYPE, tls_parse, tls_server_key_exchange_ecdhe::type, and tls_connection::version.

◆ tls_keysize_is_variable()

int tls_keysize_is_variable ( struct tls_connection * tls,
struct exchange_algorithm * exchange )
static

Check if key exchange keys have a variable size.

Parameters
tlsTLS connection
exchangeKey exchange algorithm
Return values
is_variableKey exchange keys have a variable size

TLS versions 1.2 and earlier treat FFDHE public and shared keys as unsigned big-endian integers using a minimal byte representation. For all other purposes, key exchange keys have a fixed size determined by the key exchange algorithm.

Definition at line 1260 of file tls.c.

1261 {
1262
1263 /* TLS versions 1.3 and later always have fixed-size keys */
1264 if ( tls_version ( tls, TLS_VERSION_TLS_1_3 ) )
1265 return 0;
1266
1267 /* TLS versions 1.2 and earlier have variable-sized FFDHE keys */
1268 return is_ffdhe ( exchange );
1269}

References is_ffdhe(), tls_version(), and TLS_VERSION_TLS_1_3.

Referenced by tls_channel_apply(), and tls_key_agree().

◆ tls_key_share()

int tls_key_share ( struct tls_connection * tls,
struct tls_named_group * group,
struct tls_cursor * public )
static

Share public key.

Parameters
tlsTLS connection
groupNamed group
publicPublic key to fill in
Return values
rcReturn status code

Definition at line 1286 of file tls.c.

1288 {
1289 struct secure_channel *channel = &tls->channel;
1290 struct exchange_algorithm *exchange = group->exchange;
1291 size_t pubsize = exchange->pubsize;
1292 int rc;
1293
1294 /* Check key length */
1295 if ( pubsize != public->len ) {
1296 DBGC ( tls, "TLS %p wrong public %s key size (%zd bytes)\n",
1297 tls, exchange->name, public->len );
1298 return -EINVAL_KEY_EXCHANGE;
1299 }
1300
1301 /* Share public key */
1302 if ( ( rc = channel_key_share ( channel, exchange,
1303 public->data ) ) != 0 ) {
1304 DBGC ( tls, "TLS %p could not share public %s key: %s\n",
1305 tls, exchange->name, strerror ( rc ) );
1306 return rc;
1307 }
1308
1309 return 0;
1310}
int channel_key_share(struct secure_channel *channel, struct exchange_algorithm *exchange, void *public)
Share public key.
Definition channel.c:320
uint32_t channel
RNDIS channel.
Definition netvsc.h:3
A key exchange algorithm.
Definition crypto.h:210
const char * name
Algorithm name.
Definition crypto.h:212
A secure channel.
Definition channel.h:72

References channel, tls_connection::channel, channel_key_share(), DBGC, EINVAL_KEY_EXCHANGE, group, exchange_algorithm::name, exchange_algorithm::pubsize, rc, and strerror().

Referenced by tls_client_hello(), and tls_send_client_key_exchange().

◆ tls_key_agree()

int tls_key_agree ( struct tls_connection * tls,
struct tls_named_group * group,
const struct tls_cursor * partner )
static

Agree shared secret.

Parameters
tlsTLS connection
groupNamed group
partnerPartner public key
Return values
rcReturn status code

Definition at line 1320 of file tls.c.

1322 {
1323 struct secure_channel *channel = &tls->channel;
1324 struct exchange_algorithm *exchange = group->exchange;
1325 size_t pubsize = exchange->pubsize;
1326 uint8_t *tmp;
1327 size_t pad_len;
1328 int strip;
1329 int rc;
1330
1331 /* Allocate space for potentially padded partner key */
1332 tmp = zalloc ( pubsize );
1333 if ( ! tmp ) {
1334 rc = -ENOMEM;
1335 goto err_alloc;
1336 }
1337
1338 /* Validate partner key */
1339 if ( partner->len > pubsize ) {
1340 DBGC ( tls, "TLS %p overlength partner %s key:\n",
1341 tls, exchange->name );
1342 DBGC_HDA ( tls, 0, partner->data, partner->len );
1344 goto err_len;
1345 }
1346
1347 /* TLSv1.2 and earlier may require zero-padding for FFDHE keys */
1348 strip = tls_keysize_is_variable ( tls, exchange );
1349 pad_len = ( pubsize - partner->len );
1350 if ( pad_len && ( ! strip ) ) {
1351 DBGC ( tls, "TLS %p underlength partner %s key:\n",
1352 tls, exchange->name );
1353 DBGC_HDA ( tls, 0, partner->data, partner->len );
1355 goto err_pad;
1356 }
1357 memcpy ( ( tmp + pad_len ), partner->data, partner->len );
1358
1359 /* Agree shared secret */
1360 if ( ( rc = channel_key_agree ( channel, exchange, tmp ) ) != 0 ) {
1361 DBGC ( tls, "TLS %p could not agree shared %s key: %s\n",
1362 tls, exchange->name, strerror ( rc ) );
1363 goto err_agree;
1364 }
1365
1366 err_agree:
1367 err_pad:
1368 err_len:
1369 zfree ( tmp );
1370 err_alloc:
1371 return rc;
1372}
int channel_key_agree(struct secure_channel *channel, struct exchange_algorithm *exchange, const void *partner)
Agree shared secret.
Definition channel.c:424
struct eth_slow_lacp_entity_tlv partner
Partner information.
Definition eth_slow.h:5
static int tls_keysize_is_variable(struct tls_connection *tls, struct exchange_algorithm *exchange)
Check if key exchange keys have a variable size.
Definition tls.c:1260

References channel, tls_connection::channel, channel_key_agree(), DBGC, DBGC_HDA, EINVAL_KEY_EXCHANGE, ENOMEM, group, memcpy(), exchange_algorithm::name, partner, exchange_algorithm::pubsize, rc, strerror(), tls_keysize_is_variable(), tmp, zalloc(), and zfree().

Referenced by tls_new_server_hello(), and tls_new_server_key_exchange().

◆ tls_key_encrypt()

int tls_key_encrypt ( struct tls_connection * tls,
struct tls_named_group * group,
struct asn1_builder * builder )
static

Encrypt (and implicitly bind) shared secret.

Parameters
tlsTLS connection
groupNamed group
builderASN.1 builder
Return values
rcReturn status code

Definition at line 1382 of file tls.c.

1384 {
1385 struct secure_channel *channel = &tls->channel;
1386 struct exchange_algorithm *exchange = group->exchange;
1387 struct pubkey_algorithm *pubkey;
1388 struct x509_certificate *cert;
1389 int rc;
1390
1391 /* Identify server certificate */
1392 if ( ! tls->server.chain ) {
1393 DBGC ( tls, "TLS %p has no server certificate chain\n", tls );
1394 return -ENOENT_CERT;
1395 }
1396 cert = x509_first ( tls->server.chain );
1397 if ( ! cert ) {
1398 DBGC ( tls, "TLS %p has no server certificate\n", tls );
1399 return -ENOENT_CERT;
1400 }
1401 pubkey = cert->subject.public_key.algorithm->pubkey;
1402
1403 /* Encrypt (and implicitly bind) shared secret */
1404 if ( ( rc = channel_bind_encrypt ( channel, cert, exchange, pubkey,
1405 builder ) ) != 0 ) {
1406 DBGC ( tls, "TLS %p could not encrypt %s key: %s\n",
1407 tls, exchange->name, strerror ( rc ) );
1408 return rc;
1409 }
1410
1411 return 0;
1412}
int channel_bind_encrypt(struct secure_channel *channel, struct x509_certificate *identity, struct exchange_algorithm *exchange, struct pubkey_algorithm *pubkey, struct asn1_builder *ciphertext)
Bind peer identity via shared secret encryption.
Definition channel.c:648
struct pubkey_algorithm * pubkey
Public-key algorithm (if applicable).
Definition asn1.h:435
An X.509 certificate.
Definition x509.h:216
struct x509_subject subject
Subject.
Definition x509.h:245
struct asn1_algorithm * algorithm
Public key algorithm.
Definition x509.h:54
struct x509_public_key public_key
Public key information.
Definition x509.h:66
#define ENOENT_CERT
Definition tls.c:93
static struct x509_certificate * x509_first(struct x509_chain *chain)
Get first certificate in X.509 certificate chain.
Definition x509.h:311

References x509_public_key::algorithm, tls_server::chain, channel, tls_connection::channel, channel_bind_encrypt(), DBGC, ENOENT_CERT, group, exchange_algorithm::name, asn1_algorithm::pubkey, x509_subject::public_key, rc, tls_connection::server, strerror(), x509_certificate::subject, and x509_first().

Referenced by tls_send_client_key_exchange().

◆ tls_hash_sign()

int tls_hash_sign ( struct tls_connection * tls,
struct tls_signature_hash_algorithm * sig_hash,
struct x509_certificate * cert,
struct asn1_builder * sig )
static

Create signature over parameters used to construct shared secret.

Parameters
tlsTLS connection
sig_hashSignature hash algorithm
certCertificate
sigSignature to fill in
Return values
rcReturn status code

Definition at line 1423 of file tls.c.

1426 {
1427 struct asn1_cursor *key = privkey_cursor ( tls->client.key );
1428 struct pubkey_algorithm *pubkey = sig_hash->pubkey;
1429 struct digest_algorithm *digest = sig_hash->digest;
1430 uint8_t tbshash[digest->digestsize];
1431 int rc;
1432
1433 /* Identify algorithms */
1434 if ( sig_hash->algorithm &&
1435 ( sig_hash->algorithm != cert->subject.public_key.algorithm ) ) {
1436 DBGC ( tls, "TLS %p cannot use %s public key\n",
1437 tls, cert->subject.public_key.algorithm->name );
1438 return -EPERM_KEY_EXCHANGE;
1439 }
1440 DBGC ( tls, "TLS %p signing with %s-%s\n",
1441 tls, pubkey->name, digest->name );
1442
1443 /* Calculate digest */
1444 if ( ( rc = tlskey_tbshash ( &tls->key, &tls_client, digest,
1445 NULL, 0, tbshash ) ) != 0 ) {
1446 DBGC ( tls, "TLS %p could not generate signable digest: %s\n",
1447 tls, strerror ( rc ) );
1448 return rc;
1449 }
1450
1451 /* Create signature */
1452 if ( ( rc = pubkey_sign ( pubkey, key, digest, tbshash,
1453 sig ) ) != 0 ) {
1454 DBGC ( tls, "TLS %p could not sign: %s\n",
1455 tls, strerror ( rc ) );
1456 return rc;
1457 }
1458
1459 return 0;
1460}
u8 sig
Definition CIB_PRM.h:15
static int pubkey_sign(struct pubkey_algorithm *pubkey, const struct asn1_cursor *key, struct digest_algorithm *digest, const void *value, struct asn1_builder *signature)
Definition crypto.h:376
static struct asn1_cursor * privkey_cursor(struct private_key *key)
Get private key ASN.1 cursor.
Definition privkey.h:53
const char * name
Name.
Definition asn1.h:431
An ASN.1 object cursor.
Definition asn1.h:21
TLS client state.
Definition tls.h:454
struct asn1_algorithm * algorithm
Required certificate OID-identified algorithm, if any.
Definition tls.h:362
#define EPERM_KEY_EXCHANGE
Definition tls.c:165
int tlskey_tbshash(struct tls_key_schedule *tlskey, const struct tls_endpoint *end, struct digest_algorithm *digest, const void *data, size_t len, void *tbs)
Generate signable digest value.
Definition tlskey.c:772

References tls_signature_hash_algorithm::algorithm, x509_public_key::algorithm, tls_connection::client, DBGC, tls_signature_hash_algorithm::digest, digest_algorithm::digestsize, EPERM_KEY_EXCHANGE, key, tls_client::key, tls_connection::key, asn1_algorithm::name, digest_algorithm::name, pubkey_algorithm::name, NULL, privkey_cursor(), tls_signature_hash_algorithm::pubkey, pubkey_sign(), x509_subject::public_key, rc, sig, strerror(), x509_certificate::subject, and tlskey_tbshash().

Referenced by tls_send_certificate_verify().

◆ tls_hash_verify()

int tls_hash_verify ( struct tls_connection * tls,
struct tls_signature_hash_algorithm * sig_hash,
struct x509_certificate * cert,
const struct tls_cursor * params,
const struct asn1_cursor * sig )
static

Verify signature over parameters used to construct shared secret.

Parameters
tlsTLS connection
sig_hashSignature hash algorithm
certCertificate
paramsAdditional parameters
sigSignature
Return values
rcReturn status code

Definition at line 1472 of file tls.c.

1476 {
1477 struct pubkey_algorithm *pubkey = sig_hash->pubkey;
1478 struct digest_algorithm *digest = sig_hash->digest;
1479 uint8_t tbshash[digest->digestsize];
1480 int rc;
1481
1482 /* Identify algorithms */
1483 if ( sig_hash->algorithm &&
1484 ( sig_hash->algorithm != cert->subject.public_key.algorithm ) ) {
1485 DBGC ( tls, "TLS %p cannot use %s public key\n",
1486 tls, cert->subject.public_key.algorithm->name );
1487 return -EPERM_KEY_EXCHANGE;
1488 }
1489 DBGC ( tls, "TLS %p verifying with %s-%s\n",
1490 tls, pubkey->name, digest->name );
1491
1492 /* Calculate digest */
1493 if ( ( rc = tlskey_tbshash ( &tls->key, &tls_server, digest,
1494 params->data, params->len,
1495 tbshash ) ) != 0 ) {
1496 DBGC ( tls, "TLS %p could not generate signable digest: %s\n",
1497 tls, strerror ( rc ) );
1498 return rc;
1499 }
1500
1501 /* Verify signature and bind shared secret */
1502 if ( ( rc = channel_bind_verify ( &tls->channel, cert, pubkey,
1503 digest, tbshash, sig ) ) != 0 ) {
1504 DBGC ( tls, "TLS %p failed signature verification: %s\n",
1505 tls, strerror ( rc ) );
1506 return rc;
1507 }
1508
1509 return 0;
1510}
int channel_bind_verify(struct secure_channel *channel, struct x509_certificate *identity, struct pubkey_algorithm *pubkey, struct digest_algorithm *digest, const void *value, const struct asn1_cursor *signature)
Bind peer identity via ephemeral public key signature verification.
Definition channel.c:611
TLS server state.
Definition tls.h:464

References tls_signature_hash_algorithm::algorithm, x509_public_key::algorithm, tls_connection::channel, channel_bind_verify(), tls_cursor::data, DBGC, tls_signature_hash_algorithm::digest, digest_algorithm::digestsize, EPERM_KEY_EXCHANGE, tls_connection::key, tls_cursor::len, asn1_algorithm::name, digest_algorithm::name, pubkey_algorithm::name, tls_signature_hash_algorithm::pubkey, x509_subject::public_key, rc, sig, strerror(), x509_certificate::subject, and tlskey_tbshash().

Referenced by tls_verify_signature().

◆ tls_channel_reset()

void tls_channel_reset ( struct secure_channel * channel)
static

Reset the key schedule.

Parameters
channelSecure channel

Definition at line 1524 of file tls.c.

1524 {
1525 struct tls_connection *tls =
1527
1528 /* Reset key schedule */
1529 tlskey_reset ( &tls->key );
1530}
void tlskey_reset(struct tls_key_schedule *tlskey)
Reset key schedule.
Definition tlskey.c:520

References channel, container_of, tls_connection::key, and tlskey_reset().

◆ tls_channel_apply()

int tls_channel_apply ( struct secure_channel * channel,
struct exchange_algorithm * exchange,
const void * shared,
int * accumulated )
static

Apply a new shared secret to key schedule.

Parameters
channelSecure channel
exchangeKey exchange algorithm
sharedNew shared secret
accumulatedAccumulation flag to fill in
Return values
rcReturn status code

Definition at line 1541 of file tls.c.

1543 {
1544 struct tls_connection *tls =
1546 size_t shared_len = exchange->sharedsize;
1547 int rc;
1548
1549 /* Strip leading zeros if needed */
1550 if ( tls_keysize_is_variable ( tls, exchange ) ) {
1551 /* TLS v1.2 and earlier strip leading zeros for FFDHE
1552 *
1553 * This code can be reached only with the result from
1554 * a successful FFDHE key exchange, and so the shared
1555 * secret cannot ever end up as all zeros.
1556 */
1557 while ( shared_len && ( ! *( ( const uint8_t * ) shared ) ) ) {
1558 shared++;
1559 shared_len--;
1560 }
1561 assert ( shared_len > 0 );
1562 }
1563 DBGC ( tls, "TLS %p shared (pre-master) secret:\n", tls );
1564 DBGC_HDA ( tls, 0, shared, shared_len );
1565
1566 /* Apply shared secret to key schedule */
1567 if ( ( rc = tlskey_apply ( &tls->key, shared, shared_len ) ) != 0 ) {
1568 DBGC ( tls, "TLS %p could not apply shared secret: %s\n",
1569 tls, strerror ( rc ) );
1570 return rc;
1571 }
1572
1573 /* Set accumulation flag if applicable */
1574 *accumulated = tlskey_is_accumulating ( &tls->key );
1575
1576 return 0;
1577}
size_t sharedsize
Shared secret size.
Definition crypto.h:218
int tlskey_apply(struct tls_key_schedule *tlskey, const void *shared, size_t shared_len)
Apply a new shared secret.
Definition tlskey.c:550
static int tlskey_is_accumulating(struct tls_key_schedule *tlskey)
Check if key schedule accumulates shared secrets.
Definition tlskey.h:342

References assert, channel, container_of, DBGC, DBGC_HDA, tls_connection::key, rc, exchange_algorithm::sharedsize, strerror(), tls_keysize_is_variable(), tlskey_apply(), and tlskey_is_accumulating().

◆ tls_channel_save()

int tls_channel_save ( struct secure_channel * channel,
struct secure_preshared_identity * psid )
static

Save a pre-shared key for future resumption of the key schedule.

Parameters
channelSecure channel
psidPre-shared bound peer identity
Return values
rcReturn status code

Definition at line 1586 of file tls.c.

1587 {
1588 struct tls_connection *tls =
1590 struct tls_session *session =
1591 container_of ( psid, struct tls_session, psid );
1592 int rc;
1593
1594 /* We support saving pre-shared keys only once the secure
1595 * channel has been established (since resumed connections
1596 * will not receive a certificate chain and so will have no
1597 * further opportunities to validate the bound identity).
1598 */
1599 if ( ! channel_is_established ( channel ) ) {
1600 DBGC ( tls, "TLS %p cannot save pre-shared key before "
1601 "channel is established\n", tls );
1602 return -EPERM_SAVE;
1603 }
1604
1605 /* Save key material */
1606 if ( ( rc = tlskey_save ( &tls->key, NULL, 0,
1607 &session->psk ) ) != 0 ) {
1608 DBGC ( tls, "TLS %p could not save key material: %s\n",
1609 tls, strerror ( rc ) );
1610 return rc;
1611 }
1612
1613 return 0;
1614}
struct tls_preshared_key psk
Pre-shared key.
Definition tls.h:405
#define EPERM_SAVE
Definition tls.c:169
int tlskey_save(struct tls_key_schedule *tlskey, const void *nonce, size_t nonce_len, struct tls_preshared_key *psk)
Save pre-shared key.
Definition tlskey.c:823

References channel, channel_is_established(), container_of, DBGC, EPERM_SAVE, tls_connection::key, NULL, tls_session::psid, tls_session::psk, rc, strerror(), and tlskey_save().

◆ tls_channel_load()

int tls_channel_load ( struct secure_channel * channel,
struct secure_preshared_identity * psid )
static

Load a pre-shared key and resume the key schedule.

Parameters
channelSecure channel
psidPre-shared bound peer identity
Return values
rcReturn status code

Definition at line 1623 of file tls.c.

1624 {
1625 struct tls_connection *tls =
1627 struct tls_session *session =
1628 container_of ( psid, struct tls_session, psid );
1629 int rc;
1630
1631 /* Load key material */
1632 if ( ( rc = tlskey_load ( &tls->key, tls->extended_master_secret,
1633 &session->psk ) ) != 0 ) {
1634 DBGC ( tls, "TLS %p could not load key material: %s\n",
1635 tls, strerror ( rc ) );
1636 return rc;
1637 }
1638
1639 return 0;
1640}
int extended_master_secret
Extended master secret flag.
Definition tls.h:507
int tlskey_load(struct tls_key_schedule *tlskey, int ems, const struct tls_preshared_key *psk)
Load pre-shared key.
Definition tlskey.c:866

References channel, container_of, DBGC, tls_connection::extended_master_secret, tls_connection::key, tls_session::psid, tls_session::psk, rc, strerror(), and tlskey_load().

◆ tls_channel_verify()

int tls_channel_verify ( struct secure_channel * channel,
const void * auth,
size_t len )
static

Verify authenticator value.

Parameters
channelSecure channel
authAuthenticator value
lenLength of authenticator value
Return values
rcReturn status code

Definition at line 1650 of file tls.c.

1651 {
1652 struct tls_connection *tls =
1654 int rc;
1655
1656 /* Sanity checks */
1657 if ( ( len == 0 ) || ( len != tls->verify.len ) ) {
1658 DBGC ( tls, "TLS %p invalid authenticator value:\n", tls );
1659 DBGC_HDA ( tls, 0, auth, len );
1660 return -EPERM_VERIFY;
1661 }
1662
1663 /* Generate verification data */
1664 if ( ( rc = tlskey_verify ( &tls->key, &tls_server,
1665 tls->verify.server, len ) ) != 0 ) {
1666 DBGC ( tls, "TLS %p could not generate server verification: "
1667 "%s\n", tls, strerror ( rc ) );
1668 return rc;
1669 }
1670
1671 /* Verify data */
1672 if ( memcmp ( tls->verify.server, auth, len ) != 0 ) {
1673 DBGC ( tls, "TLS %p incorrect authenticator value:\n", tls );
1674 return -EPERM_VERIFY;
1675 }
1676
1677 return 0;
1678}
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition string.c:115
#define EPERM_VERIFY
Definition tls.c:153
int tlskey_verify(struct tls_key_schedule *tlskey, const struct tls_endpoint *end, void *verify, size_t verify_len)
Generate verification data.
Definition tlskey.c:630

References channel, container_of, DBGC, DBGC_HDA, EPERM_VERIFY, tls_connection::key, len, tls_verify_data::len, memcmp(), rc, tls_verify_data::server, strerror(), tlskey_verify(), and tls_connection::verify.

◆ tls_set_session_id()

void tls_set_session_id ( struct tls_connection * tls)
static

Set a random session ID.

Parameters
tlsTLS connection

The session ID will be generated deterministically using the per-connection ephemeral secret and will therefore be guaranteed to differ between connections (including restarted connections).

Definition at line 1705 of file tls.c.

1705 {
1706 struct tls_session *session = tls->session;
1707
1708 /* Generate session ID */
1709 tls_random ( tls, session->id.data, sizeof ( session->id.data ) );
1710 session->id.len = sizeof ( session->id.data );
1711}

References tls_session_id::data, tls_session::id, tls_session_id::len, tls_connection::session, and tls_random().

Referenced by tls_save(), and tls_session().

◆ tls_session()

int tls_session ( struct tls_connection * tls,
const char * name )
static

Find or create session for TLS connection.

Parameters
tlsTLS connection
nameServer name
Return values
rcReturn status code

Definition at line 1720 of file tls.c.

1720 {
1721 struct tls_session *session;
1722 char *name_copy;
1723 int rc;
1724
1725 /* Find existing matching session, if any */
1726 list_for_each_entry ( session, &tls_sessions, list ) {
1727 if ( ( strcmp ( name, session->name ) == 0 ) &&
1728 ( tls->server.root == session->root ) &&
1729 ( tls->client.key == session->key ) ) {
1730 ref_get ( &session->refcnt );
1731 tls->session = session;
1732 DBGC ( tls, "TLS %p joining %s session %s:\n", tls,
1733 ( session->ticket.len ? "stateless" :
1734 "stateful" ), name );
1735 DBGC_HDA ( tls, 0, session->id.data, session->id.len );
1736 return 0;
1737 }
1738 }
1739
1740 /* Create new session */
1741 session = zalloc ( sizeof ( *session ) + strlen ( name )
1742 + 1 /* NUL */ );
1743 if ( ! session ) {
1744 rc = -ENOMEM;
1745 goto err_alloc;
1746 }
1747 ref_init ( &session->refcnt, free_tls_session );
1748 name_copy = ( ( ( void * ) session ) + sizeof ( *session ) );
1749 strcpy ( name_copy, name );
1750 session->name = name_copy;
1751 session->root = x509_root_get ( tls->server.root );
1752 session->key = privkey_get ( tls->client.key );
1753 INIT_LIST_HEAD ( &session->conn );
1754 list_add ( &session->list, &tls_sessions );
1755
1756 /* Generate random initial session ID */
1757 tls->session = session;
1758 tls_set_session_id ( tls );
1759 DBGC ( tls, "TLS %p created session %s:\n", tls, name );
1760 DBGC_HDA ( tls, 0, session->id.data, session->id.len );
1761
1762 return 0;
1763
1764 ref_put ( &session->refcnt );
1765 err_alloc:
1766 return rc;
1767}
#define list_add(new, head)
Add a new entry to the head of a list.
Definition list.h:70
static struct private_key * privkey_get(struct private_key *key)
Get reference to private key.
Definition privkey.h:31
#define ref_get(refcnt)
Get additional reference to object.
Definition refcnt.h:93
#define ref_init(refcnt, free)
Initialise a reference counter.
Definition refcnt.h:65
int strcmp(const char *first, const char *second)
Compare strings.
Definition string.c:174
char * strcpy(char *dest, const char *src)
Copy string.
Definition string.c:378
static void free_tls_session(struct refcnt *refcnt)
Free TLS session.
Definition tls.c:385
static void tls_set_session_id(struct tls_connection *tls)
Set a random session ID.
Definition tls.c:1705
static struct x509_root * x509_root_get(struct x509_root *root)
Get reference to X.509 root certificate list.
Definition x509.h:393

References tls_connection::client, tls_session::conn, tls_session_id::data, DBGC, DBGC_HDA, ENOMEM, free_tls_session(), tls_session::id, INIT_LIST_HEAD, tls_client::key, tls_session::key, tls_cursor::len, tls_session_id::len, tls_session::list, list_add, list_for_each_entry, name, tls_session::name, privkey_get(), rc, ref_get, ref_init, ref_put, tls_session::refcnt, tls_server::root, tls_session::root, tls_connection::server, tls_connection::session, strcmp(), strcpy(), strlen(), tls_session::ticket, tls_set_session_id(), x509_root_get(), and zalloc().

◆ tls_save()

int tls_save ( struct tls_connection * tls)
static

Save session for future resumption.

Parameters
tlsTLS connection
Return values
rcReturn status code

Definition at line 1775 of file tls.c.

1775 {
1776 struct tls_session *session = tls->session;
1777 const char *name = session->name;
1778 int rc;
1779
1780 /* Sanity check */
1781 assert ( tls->new_id.len || tls->new_ticket.len );
1782
1783 /* Clear any existing session state */
1784 tls_set_session_id ( tls );
1785 zfree ( session->ticket.data );
1786 session->ticket.data = NULL;
1787 session->ticket.len = 0;
1788
1789 /* Save pre-shared key and peer identity */
1790 if ( ( rc = channel_save ( &tls->channel, &session->psid ) ) != 0 ) {
1791 DBGC ( tls, "TLS %p could not save: %s\n",
1792 tls, strerror ( rc ) );
1793 return rc;
1794 }
1795
1796 /* Record new session ID, if provided */
1797 if ( tls->new_id.len )
1798 memcpy ( &session->id, &tls->new_id, sizeof ( session->id ) );
1799 DBGC ( tls, "TLS %p %s session %s:\n",
1800 tls, ( tls->new_id.len ? "saved stateful" : "reset" ), name );
1801 DBGC_HDA ( tls, 0, session->id.data, session->id.len );
1802
1803 /* Record (and consume) new session ticket, if provided */
1804 if ( tls->new_ticket.len ) {
1805 session->ticket.data = tls->new_ticket.data;
1806 session->ticket.len = tls->new_ticket.len;
1807 tls->new_ticket.data = NULL;
1808 tls->new_ticket.len = 0;
1809 DBGC ( tls, "TLS %p saved stateless session %s:\n",
1810 tls, name );
1811 DBGC_HDA ( tls, 0, session->ticket.data,
1812 session->ticket.len );
1813 }
1814
1815 return 0;
1816}
int channel_save(struct secure_channel *channel, struct secure_preshared_identity *psid)
Save a pre-shared key.
Definition channel.c:738
struct tls_session_id new_id
New session ID (if any).
Definition tls.h:487

References assert, tls_connection::channel, channel_save(), tls_cursor::data, tls_session_id::data, DBGC, DBGC_HDA, tls_session::id, tls_cursor::len, tls_session_id::len, memcpy(), name, tls_session::name, tls_connection::new_id, tls_connection::new_ticket, NULL, tls_session::psid, rc, tls_connection::session, strerror(), tls_session::ticket, tls_set_session_id(), and zfree().

Referenced by tls_establish().

◆ tls_resume()

int tls_resume ( struct tls_connection * tls)
static

Resume session.

Parameters
tlsTLS connection
Return values
rcReturn status code

Definition at line 1824 of file tls.c.

1824 {
1825 struct tls_session *session = tls->session;
1826 int rc;
1827
1828 DBGC ( tls, "TLS %p resuming %s session %s\n",
1829 tls, ( session->ticket.len ? "stateless" : "stateful" ),
1830 session->name );
1831
1832 /* Load pre-shared key and peer identity */
1833 if ( ( rc = channel_load ( &tls->channel, &session->psid ) ) != 0 ) {
1834 DBGC ( tls, "TLS %p could not resume: %s\n",
1835 tls, strerror ( rc ) );
1836 return rc;
1837 }
1838
1839 return 0;
1840}
int channel_load(struct secure_channel *channel, struct secure_preshared_identity *psid)
Load a pre-shared key.
Definition channel.c:783

References tls_connection::channel, channel_load(), DBGC, tls_cursor::len, tls_session::name, tls_session::psid, rc, tls_connection::session, strerror(), and tls_session::ticket.

Referenced by tls_new_server_hello().

◆ tls_tx_resume()

void tls_tx_resume ( struct tls_connection * tls)
static

Resume TX state machine.

Parameters
tlsTLS connection

Definition at line 1854 of file tls.c.

1854 {
1855 process_add ( &tls->tx.process );
1856}
void process_add(struct process *process)
Add process to process list.
Definition process.c:60

References tls_tx::process, process_add(), and tls_connection::tx.

Referenced by tls_new_finished(), tls_new_server_hello(), tls_restart(), tls_tx_resume_all(), tls_tx_step(), and tls_validator_done().

◆ tls_restart()

void tls_restart ( struct tls_connection * tls)
static

Restart negotiation.

Parameters
tlsTLS connection

Definition at line 1875 of file tls.c.

1875 {
1876
1877 /* Sanity check */
1878 assert ( ! tls->tx.pending );
1879 assert ( ! is_pending ( &tls->client.negotiation ) );
1880 assert ( ! is_pending ( &tls->server.negotiation ) );
1881 assert ( ! is_pending ( &tls->server.validation ) );
1882
1883 /* Reset secure channel */
1884 channel_reopen ( &tls->channel );
1885
1886 /* Reset cipher suite (leaving ciphers intact) */
1888
1889 /* (Re)start negotiation */
1891 tls_tx_resume ( tls );
1892 pending_get ( &tls->client.negotiation );
1893 pending_get ( &tls->server.negotiation );
1894}
void channel_reopen(struct secure_channel *channel)
Reopen secure channel.
Definition channel.c:1269
unsigned int pending
Pending transmissions.
Definition tls.h:432
@ TLS_TX_CLIENT_HELLO
Definition tls.h:219

References assert, tls_connection::channel, channel_reopen(), tls_connection::client, is_pending(), tls_client::negotiation, tls_server::negotiation, tls_tx::pending, pending_get(), tls_connection::server, tls_connection::suite, tls_cipher_suite_null, TLS_TX_CLIENT_HELLO, tls_tx_resume(), tls_connection::tx, and tls_server::validation.

Referenced by add_tls(), and tls_new_hello_request().

◆ tls_establish()

int tls_establish ( struct tls_connection * tls)
static

Establish secure channel.

Parameters
tlsTLS connection
Return values
rcReturn status code

Definition at line 1902 of file tls.c.

1902 {
1903 struct tls_session *session = tls->session;
1904 int rc;
1905
1906 /* Establish channel as trusted for server name */
1907 if ( ( rc = channel_establish ( &tls->channel, session->name,
1908 tls->server.root ) ) != 0 ) {
1909 DBGC ( tls, "TLS %p could not establish channel: %s\n",
1910 tls, strerror ( rc ) );
1911 return rc;
1912 }
1913
1914 /* Save session for future resumption, if applicable */
1915 if ( tls->new_id.len || tls->new_ticket.len )
1916 tls_save ( tls );
1917
1918 /* Move to end of session's connection list and allow other
1919 * connections to start making progress.
1920 */
1921 list_del ( &tls->list );
1922 list_add_tail ( &tls->list, &session->conn );
1923 tls_tx_resume_all ( session );
1924
1925 /* Send notification of a window change */
1927
1928 return 0;
1929}
int channel_establish(struct secure_channel *channel, const char *name, struct x509_root *root)
Establish channel as trusted for application data.
Definition channel.c:986
#define list_add_tail(new, head)
Add a new entry to the tail of a list.
Definition list.h:94
static int tls_save(struct tls_connection *tls)
Save session for future resumption.
Definition tls.c:1775
void xfer_window_changed(struct interface *intf)
Report change of flow control window.
Definition xfer.c:147

References tls_connection::channel, channel_establish(), tls_session::conn, DBGC, tls_cursor::len, tls_session_id::len, tls_connection::list, list_add_tail, list_del, tls_session::name, tls_connection::new_id, tls_connection::new_ticket, tls_connection::plainstream, rc, tls_server::root, tls_connection::server, tls_connection::session, strerror(), tls_save(), tls_tx_resume_all(), and xfer_window_changed().

Referenced by tls_new_finished(), and tls_send_finished().

◆ tls_alloc_handshake()

struct io_buffer * tls_alloc_handshake ( struct tls_connection * tls,
struct tls_cursor * cursor,
unsigned int type )
static

Allocate Handshake record.

Parameters
tlsTLS connection
cursorCursor to hold handshake message
typeRecord type
Return values
iobufI/O buffer, or NULL on error

Definition at line 1939 of file tls.c.

1941 {
1942 union tls_handshake_header *handshake;
1943 struct io_buffer *iobuf;
1944
1945 /* Allocate I/O buffer */
1946 iobuf = tls_alloc_iob ( tls, sizeof ( *handshake ) + cursor->len );
1947 if ( ! iobuf )
1948 return NULL;
1949
1950 /* Construct handshake header */
1951 handshake = iob_put ( iobuf, sizeof ( *handshake ) );
1952 handshake->type_len = htonl ( cursor->len );
1953 handshake->type = type;
1954
1955 /* Construct space for handshake message */
1956 cursor->data = iob_put ( iobuf, cursor->len );
1957
1958 return iobuf;
1959}
#define htonl(value)
Definition byteswap.h:134
A TLS handshake header.
Definition tls.h:46
uint8_t type
Type.
Definition tls.h:48
uint32_t type_len
Type and length.
Definition tls.h:50

References tls_cursor::data, htonl, iob_put, tls_cursor::len, NULL, tls_alloc_iob(), tls_handshake_header::type, type, and tls_handshake_header::type_len.

Referenced by tls_client_hello(), tls_send_certificate(), tls_send_certificate_verify(), tls_send_client_key_exchange(), and tls_send_finished().

◆ tls_send_handshake()

int tls_send_handshake ( struct tls_connection * tls,
struct io_buffer * iobuf )
static

Transmit Handshake record.

Parameters
tlsTLS connection
iobufI/O buffer
Return values
rcReturn status code

Definition at line 1968 of file tls.c.

1969 {
1970 int rc;
1971
1972 /* Send record */
1973 if ( ( rc = tls_send_record ( tls, TLS_TYPE_HANDSHAKE,
1974 iob_disown ( iobuf ) ) ) != 0 ) {
1975 return rc;
1976 }
1977
1978 return 0;
1979}

References iob_disown, rc, tls_send_record(), and TLS_TYPE_HANDSHAKE.

Referenced by tls_send_certificate(), tls_send_certificate_verify(), tls_send_client_hello(), tls_send_client_key_exchange(), and tls_send_finished().

◆ tls_send_client_hello()

int tls_send_client_hello ( struct tls_connection * tls)
static

Transmit Client Hello record.

Parameters
tlsTLS connection
Return values
rcReturn status code

Definition at line 2190 of file tls.c.

2190 {
2191
2192 return tls_client_hello ( tls, tls_send_handshake );
2193}
static int tls_send_handshake(struct tls_connection *tls, struct io_buffer *iobuf)
Transmit Handshake record.
Definition tls.c:1968

References tls_client_hello(), and tls_send_handshake().

Referenced by tls_tx_step().

◆ tls_send_certificate()

int tls_send_certificate ( struct tls_connection * tls)
static

Transmit Certificate record.

Parameters
tlsTLS connection
Return values
rcReturn status code

Definition at line 2201 of file tls.c.

2201 {
2202 struct {
2203 struct tls_certificate certificate;
2204 struct tls_certificate_entry entry;
2205 } s;
2206 struct tls_certificate *certificate = &s.certificate;
2207 struct tls_certificate_entry *entry = &s.entry;
2208 struct tls_cursor cursor;
2209 struct tls_cursor *next;
2210 struct x509_link *link;
2211 struct x509_certificate *cert;
2212 struct io_buffer *iobuf;
2213 unsigned int version;
2214 int rc;
2215
2216 /* Initialise data structures */
2217 memset ( &s, 0, sizeof ( s ) );
2218 version = tls->version;
2219
2220 /* Sanity check */
2221 if ( ! tls->client.chain ) {
2222 DBGC ( tls, "TLS %p has no client certificate chain\n", tls );
2223 rc = -ENOENT_CERT;
2224 goto err_chain;
2225 }
2226
2227 /* Prepare Certificate */
2229 cert = link->cert;
2230 DBGC ( tls, "TLS %p sending client certificate %s\n",
2231 tls, x509_name ( cert ) );
2232 entry->cert.len = cert->raw.len;
2234 entry, &cursor ) ) != 0 ) {
2235 DBGC ( tls, "TLS %p could not size CertificateEntry: "
2236 "%s\n", tls, strerror ( rc ) );
2237 goto err_size;
2238 }
2239 certificate->list.len += cursor.len;
2240 }
2241 if ( ( rc = tls_size ( tls_certificate, version, certificate,
2242 &cursor ) ) != 0 ) {
2243 DBGC ( tls, "TLS %p could not size Certificate: %s\n",
2244 tls, strerror ( rc ) );
2245 goto err_size;
2246 }
2247
2248 /* Allocate I/O buffer */
2249 iobuf = tls_alloc_handshake ( tls, &cursor, TLS_CERTIFICATE );
2250 if ( ! iobuf ) {
2251 rc = -ENOMEM;
2252 goto err_alloc;
2253 }
2254
2255 /* Build Certificate */
2256 tls_build ( tls_certificate, version, certificate, &cursor );
2257 next = &certificate->list;
2259 cert = link->cert;
2260 entry->cert.data = ( ( void * ) cert->raw.data );
2261 entry->cert.len = cert->raw.len;
2262 entry->next.len = 0;
2264 next = &entry->next;
2265 }
2266 assert ( next->data == iobuf->tail );
2267
2268 /* Transmit record */
2269 if ( ( rc = tls_send_handshake ( tls, iob_disown ( iobuf ) ) ) != 0 )
2270 goto err_send;
2271
2272 err_send:
2273 free_iob ( iobuf );
2274 err_alloc:
2275 err_size:
2276 err_chain:
2277 return rc;
2278}
u32 link
Link to next descriptor.
Definition ar9003_mac.h:1
uint32_t next
Next descriptor address.
Definition dwmac.h:11
const void * data
Start of data.
Definition asn1.h:23
size_t len
Length of data.
Definition asn1.h:25
void * tail
End of data.
Definition iobuf.h:115
CertificateEntry descriptor.
Definition tlsfmt.h:400
struct tls_cursor next
Next certificate.
Definition tlsfmt.h:409
struct tls_cursor cert
Certificate data.
Definition tlsfmt.h:402
Certificate descriptor.
Definition tlsfmt.h:392
struct tls_cursor list
Certificate list.
Definition tlsfmt.h:396
struct asn1_cursor raw
Raw certificate.
Definition x509.h:231
struct list_head links
List of links.
Definition x509.h:205
#define TLS_CERTIFICATE
Definition tls.h:94
const char * x509_name(struct x509_certificate *cert)
Get X.509 certificate display name.
Definition x509.c:147

References assert, tls_certificate_entry::cert, tls_client::chain, tls_connection::client, asn1_cursor::data, tls_cursor::data, DBGC, ENOENT_CERT, ENOMEM, free_iob(), iob_disown, asn1_cursor::len, tls_cursor::len, link, x509_chain::links, io_buffer::list, tls_certificate::list, list_for_each_entry, memset(), next, tls_certificate_entry::next, x509_certificate::raw, rc, strerror(), io_buffer::tail, tls_alloc_handshake(), tls_build, TLS_CERTIFICATE, tls_send_handshake(), tls_size, tls_connection::version, version, and x509_name().

Referenced by tls_tx_step().

◆ tls_send_client_key_exchange()

int tls_send_client_key_exchange ( struct tls_connection * tls)
static

Transmit Client Key Exchange record.

Parameters
tlsTLS connection
Return values
rcReturn status code

Definition at line 2286 of file tls.c.

2286 {
2287 struct asn1_builder builder = { NULL, 0 };
2288 struct tls_cipher_suite *suite = tls->suite;
2289 struct tls_named_group *group = tls->group;
2290 struct exchange_algorithm *exchange = group->exchange;
2291 const uint8_t *map = suite->exchange->map;
2292 union tls_client_key_exchange kex;
2293 struct tls_cursor cursor;
2294 struct io_buffer *iobuf;
2295 int rc;
2296
2297 /* Encrypt (and implicitly bind) shared secret, if applicable */
2298 if ( is_key_transport ( exchange ) ) {
2299 if ( ( rc = tls_key_encrypt ( tls, group, &builder ) ) != 0 )
2300 goto err_encrypt;
2301 kex.cursor.data = builder.data;
2302 kex.cursor.len = builder.len;
2303 } else {
2304 kex.cursor.data = NULL;
2305 kex.cursor.len = exchange->pubsize;
2306 }
2307
2308 /* Prepare ClientKeyExchange structure */
2309 if ( ( rc = tls_size_map ( map, tls->version, kex.desc,
2310 &cursor ) ) != 0 ) {
2311 DBGC ( tls, "TLS %p could not size ClientKeyExchange: %s\n",
2312 tls, strerror ( rc ) );
2313 goto err_size;
2314 }
2315
2316 /* Allocate I/O buffer */
2317 iobuf = tls_alloc_handshake ( tls, &cursor, TLS_CLIENT_KEY_EXCHANGE );
2318 if ( ! iobuf ) {
2319 rc = -ENOMEM;
2320 goto err_alloc;
2321 }
2322
2323 /* Build ClientKeyExchange structure */
2324 tls_build_map ( map, tls->version, kex.desc, &cursor );
2325 if ( ( ! is_key_transport ( exchange ) ) &&
2326 ( ( rc = tls_key_share ( tls, group, &kex.cursor ) ) != 0 ) ) {
2327 goto err_share;
2328 }
2329
2330 /* Transmit record */
2331 if ( ( rc = tls_send_handshake ( tls, iob_disown ( iobuf ) ) ) != 0 )
2332 goto err_send;
2333
2334 /* Generate master secret */
2335 if ( ( rc = tlskey_master ( &tls->key,
2336 tls->extended_master_secret ) ) != 0 ) {
2337 DBGC ( tls, "TLS %p could not generate master secret: %s\n",
2338 tls, strerror ( rc ) );
2339 goto err_master;
2340 }
2341
2342 err_master:
2343 err_send:
2344 err_share:
2345 free_iob ( iobuf );
2346 err_alloc:
2347 err_size:
2348 err_encrypt:
2349 zfree ( builder.data );
2350 return rc;
2351}
static int is_key_transport(struct exchange_algorithm *exchange)
Definition crypto.h:409
static __always_inline int struct dma_mapping * map
Definition dma.h:184
An ASN.1 object builder.
Definition asn1.h:29
void * data
Data.
Definition asn1.h:36
size_t len
Length of data.
Definition asn1.h:38
const uint8_t * map
ClientKeyExchange descriptor mapping.
Definition tls.h:255
static int tls_key_encrypt(struct tls_connection *tls, struct tls_named_group *group, struct asn1_builder *builder)
Encrypt (and implicitly bind) shared secret.
Definition tls.c:1382
#define TLS_CLIENT_KEY_EXCHANGE
Definition tls.h:99
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
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.
Definition tlsfmt.c:658
int tlskey_master(struct tls_key_schedule *tlskey, int ems)
Generate master secret.
Definition tlskey.c:585
ClientKeyExchange descriptor (unified).
Definition tlsfmt.h:477

References tls_client_key_exchange::cursor, asn1_builder::data, tls_cursor::data, DBGC, tls_client_key_exchange::desc, ENOMEM, tls_cipher_suite::exchange, tls_connection::extended_master_secret, free_iob(), group, tls_connection::group, iob_disown, is_key_transport(), tls_connection::key, asn1_builder::len, tls_cursor::len, map, tls_key_exchange_algorithm::map, NULL, exchange_algorithm::pubsize, rc, strerror(), tls_connection::suite, tls_alloc_handshake(), tls_build_map(), TLS_CLIENT_KEY_EXCHANGE, tls_key_encrypt(), tls_key_share(), tls_send_handshake(), tls_size_map(), tlskey_master(), tls_connection::version, and zfree().

Referenced by tls_tx_step().

◆ tls_send_certificate_verify()

int tls_send_certificate_verify ( struct tls_connection * tls)
static

Transmit Certificate Verify record.

Parameters
tlsTLS connection
Return values
rcReturn status code

Definition at line 2359 of file tls.c.

2359 {
2360 struct asn1_builder builder = { NULL, 0 };
2361 struct tls_signature_hash_algorithm *sig_hash;
2363 struct tls_digitally_signed dsig;
2364 struct x509_certificate *cert;
2365 struct pubkey_algorithm *pubkey;
2366 struct digest_algorithm *digest;
2367 struct tls_cursor cursor;
2368 struct io_buffer *iobuf;
2369 int rc;
2370
2371 /* Identify client certificate */
2372 if ( ! tls->client.chain ) {
2373 DBGC ( tls, "TLS %p has no client certificate chain\n", tls );
2374 rc = -ENOENT_CERT;
2375 goto err_chain;
2376 }
2377 cert = x509_first ( tls->client.chain );
2378 if ( ! cert ) {
2379 DBGC ( tls, "TLS %p has no client certificate\n", tls );
2380 rc = -ENOENT_CERT;
2381 goto err_cert;
2382 }
2383 pubkey = cert->subject.public_key.algorithm->pubkey;
2384
2385 /* Identify signature and hash algorithm */
2386 if ( tls_version ( tls, TLS_VERSION_TLS_1_2 ) ) {
2387
2388 /* TLSv1.2 and above use explicit algorithm identifiers */
2389 digest = tls->key.digest;
2390 sig_hash = tls_signature_hash_algorithm ( pubkey, digest );
2391 if ( ! sig_hash ) {
2392 DBGC ( tls, "TLS %p could not identify (%s,%s) "
2393 "signature and hash algorithm\n", tls,
2394 pubkey->name, digest->name );
2396 goto err_sig_hash;
2397 }
2398
2399 } else {
2400
2401 /* TLSv1.1 and below use fixed algorithms */
2402 sig_hash = &tmp;
2403 memset ( sig_hash, 0, sizeof ( *sig_hash ) );
2404 sig_hash->pubkey = pubkey;
2405 sig_hash->digest = ( ( pubkey == &rsa_algorithm ) ?
2407 }
2408
2409 /* Create signature */
2410 if ( ( rc = tls_hash_sign ( tls, sig_hash, cert, &builder ) ) != 0 )
2411 goto err_sign;
2412
2413 /* Prepare DigitallySigned structure */
2414 dsig.sig_hash = &sig_hash->code;
2415 dsig.sig.data = builder.data;
2416 dsig.sig.len = builder.len;
2417 if ( ( rc = tls_size ( tls_digitally_signed, tls->version,
2418 &dsig, &cursor ) ) != 0 ) {
2419 DBGC ( tls, "TLS %p could not size DigitallySigned: %s\n",
2420 tls, strerror ( rc ) );
2421 goto err_size;
2422 }
2423
2424 /* Allocate I/O buffer */
2425 iobuf = tls_alloc_handshake ( tls, &cursor, TLS_CERTIFICATE_VERIFY );
2426 if ( ! iobuf ) {
2427 rc = -ENOMEM;
2428 goto err_alloc;
2429 }
2430
2431 /* Build DigitallySigned structure */
2432 tls_build ( tls_digitally_signed, tls->version, &dsig, &cursor );
2433
2434 /* Transmit record */
2435 if ( ( rc = tls_send_handshake ( tls, iob_disown ( iobuf ) ) ) != 0 )
2436 goto err_send;
2437
2438 err_send:
2439 free_iob ( iobuf );
2440 err_alloc:
2441 err_size:
2442 err_sign:
2443 err_sig_hash:
2444 err_cert:
2445 err_chain:
2446 zfree ( builder.data );
2447 return rc;
2448}
struct digest_algorithm sha1_algorithm
DigitallySigned descriptor.
Definition tlsfmt.h:491
struct digest_algorithm * digest
Digest algorithm.
Definition tlskey.h:117
struct pubkey_algorithm rsa_algorithm
Definition tls.c:199
static int tls_hash_sign(struct tls_connection *tls, struct tls_signature_hash_algorithm *sig_hash, struct x509_certificate *cert, struct asn1_builder *sig)
Create signature over parameters used to construct shared secret.
Definition tls.c:1423
#define ENOTSUP_SIG_HASH
Definition tls.c:137
static struct tls_signature_hash_algorithm * tls_signature_hash_algorithm(struct pubkey_algorithm *pubkey, struct digest_algorithm *digest)
Find TLS signature and hash algorithm.
Definition tls.c:1019
#define TLS_CERTIFICATE_VERIFY
Definition tls.h:98

References x509_public_key::algorithm, tls_client::chain, tls_connection::client, tls_signature_hash_algorithm::code, asn1_builder::data, tls_cursor::data, DBGC, tls_key_schedule::digest, tls_signature_hash_algorithm::digest, ENOENT_CERT, ENOMEM, ENOTSUP_SIG_HASH, free_iob(), iob_disown, tls_connection::key, asn1_builder::len, tls_cursor::len, md5_sha1_algorithm, memset(), digest_algorithm::name, pubkey_algorithm::name, NULL, asn1_algorithm::pubkey, tls_signature_hash_algorithm::pubkey, x509_subject::public_key, rc, rsa_algorithm, sha1_algorithm, tls_digitally_signed::sig, tls_digitally_signed::sig_hash, strerror(), x509_certificate::subject, tls_alloc_handshake(), tls_build, TLS_CERTIFICATE_VERIFY, tls_hash_sign(), tls_send_handshake(), tls_signature_hash_algorithm(), tls_size, tls_version(), TLS_VERSION_TLS_1_2, tmp, tls_connection::version, x509_first(), and zfree().

Referenced by tls_tx_step().

◆ tls_send_change_cipher()

int tls_send_change_cipher ( struct tls_connection * tls)
static

Transmit Change Cipher record.

Parameters
tlsTLS connection
Return values
rcReturn status code

Definition at line 2456 of file tls.c.

2456 {
2457 static const struct {
2458 uint8_t spec;
2459 } __attribute__ (( packed )) change_cipher = {
2460 .spec = TLS_CHANGE_CIPHER_SPEC,
2461 };
2462 int rc;
2463
2464 /* Transmit record */
2466 &change_cipher,
2467 sizeof ( change_cipher ) ) ) != 0 ) {
2468 return rc;
2469 }
2470
2471 /* Change transmit cipher spec */
2472 if ( ( rc = tls_change_cipher ( tls, &tls->tx.cipherspec,
2473 &tls_application ) ) != 0 ) {
2474 return rc;
2475 }
2476
2477 return 0;
2478}
uint16_t spec
ENA specification version.
Definition ena.h:15
#define TLS_CHANGE_CIPHER_SPEC
Change cipher spec magic byte.
Definition tls.h:78
#define TLS_TYPE_CHANGE_CIPHER
Change cipher content type.
Definition tls.h:75
const struct tls_phase tls_application
Application traffic phase.
Definition tlskey.c:151

References __attribute__, tls_tx::cipherspec, rc, spec, tls_application, tls_change_cipher(), TLS_CHANGE_CIPHER_SPEC, tls_send_plaintext(), TLS_TYPE_CHANGE_CIPHER, and tls_connection::tx.

Referenced by tls_tx_step().

◆ tls_send_finished()

int tls_send_finished ( struct tls_connection * tls)
static

Transmit Finished record.

Parameters
tlsTLS connection
Return values
rcReturn status code

Definition at line 2486 of file tls.c.

2486 {
2487 struct tls_cipherspec *cipherspec = &tls->tx.cipherspec;
2488 size_t verify_len = tls->verify.len;
2489 struct tls_cursor cursor;
2490 struct io_buffer *iobuf;
2491 int rc;
2492
2493 /* Allocate I/O buffer */
2494 cursor.len = verify_len;
2495 iobuf = tls_alloc_handshake ( tls, &cursor, TLS_FINISHED );
2496 if ( ! iobuf ) {
2497 rc = -ENOMEM;
2498 goto err_alloc;
2499 }
2500
2501 /* Construct client verification data */
2502 if ( ( rc = tlskey_verify ( &tls->key, &tls_client, tls->verify.client,
2503 verify_len ) ) != 0 ) {
2504 DBGC ( tls, "TLS %p could not generate client verification: "
2505 "%s\n", tls, strerror ( rc ) );
2506 goto err_verify;
2507 }
2508 memcpy ( cursor.data, tls->verify.client, verify_len );
2509
2510 /* TLS version 1.3 has an awkward design quirk in which the
2511 * application traffic secret must be generated using the
2512 * digest state prior to sending the client Finished, but the
2513 * corresponding application traffic keys must not be
2514 * activated until after sending the record.
2515 */
2516 if ( tls_version ( tls, TLS_VERSION_TLS_1_3 ) &&
2517 ( ( rc = tls_prep_cipher ( tls, cipherspec,
2518 &tls_application ) ) != 0 ) ) {
2519 goto err_prep;
2520 }
2521
2522 /* Transmit record */
2523 if ( ( rc = tls_send_handshake ( tls, iob_disown ( iobuf ) ) ) != 0 )
2524 goto err_send;
2525
2526 /* Change the (already prepared) cipher specification */
2527 if ( tls_version ( tls, TLS_VERSION_TLS_1_3 ) &&
2528 ( ( rc = tls_change_cipher ( tls, cipherspec, NULL ) ) != 0 ) ) {
2529 goto err_change;
2530 }
2531
2532 /* Mark client as finished */
2533 pending_put ( &tls->client.negotiation );
2534
2535 /* If server has finished, then establish the secure channel */
2536 if ( ( ! is_pending ( &tls->server.negotiation ) ) &&
2537 ( ( rc = tls_establish ( tls ) ) != 0 ) ) {
2538 goto err_establish;
2539 }
2540
2541 err_establish:
2542 err_change:
2543 err_send:
2544 err_prep:
2545 err_verify:
2546 free_iob ( iobuf );
2547 err_alloc:
2548 return rc;
2549}
static int tls_establish(struct tls_connection *tls)
Establish secure channel.
Definition tls.c:1902
#define TLS_FINISHED
Definition tls.h:100

References tls_tx::cipherspec, tls_connection::client, tls_verify_data::client, tls_cursor::data, DBGC, ENOMEM, free_iob(), iob_disown, is_pending(), tls_connection::key, tls_cursor::len, tls_verify_data::len, memcpy(), tls_client::negotiation, tls_server::negotiation, NULL, pending_put(), rc, tls_connection::server, strerror(), tls_alloc_handshake(), tls_application, tls_change_cipher(), tls_establish(), TLS_FINISHED, tls_prep_cipher(), tls_send_handshake(), tls_version(), TLS_VERSION_TLS_1_3, tlskey_verify(), tls_connection::tx, and tls_connection::verify.

Referenced by tls_tx_step().

◆ tls_new_change_cipher()

int tls_new_change_cipher ( struct tls_connection * tls,
struct io_buffer * iobuf )
static

Receive new Change Cipher record.

Parameters
tlsTLS connection
iobufI/O buffer
Return values
rcReturn status code

Definition at line 2581 of file tls.c.

2582 {
2583 const struct {
2584 uint8_t spec;
2585 } __attribute__ (( packed )) *change_cipher = iobuf->data;
2586 size_t len = iob_len ( iobuf );
2587
2588 /* Sanity check */
2589 if ( ( sizeof ( *change_cipher ) != len ) ||
2590 ( change_cipher->spec != TLS_CHANGE_CIPHER_SPEC ) ) {
2591 DBGC ( tls, "TLS %p received invalid Change Cipher\n", tls );
2592 DBGC_HD ( tls, change_cipher, len );
2593 return -EINVAL_CHANGE_CIPHER;
2594 }
2595 iob_pull ( iobuf, sizeof ( *change_cipher ) );
2596
2597 /* Schedule change to application traffic keys, if applicable */
2598 if ( ! tls_version ( tls, TLS_VERSION_TLS_1_3 ) )
2600
2601 return 0;
2602}
#define DBGC_HD(...)
Definition compiler.h:532
#define iob_pull(iobuf, len)
Definition iobuf.h:167
#define EINVAL_CHANGE_CIPHER
Definition tls.c:53

References __attribute__, tls_rx::cipherspec, io_buffer::data, DBGC, DBGC_HD, EINVAL_CHANGE_CIPHER, iob_len(), iob_pull, len, tls_cipherspec::pending, tls_connection::rx, spec, tls_application, TLS_CHANGE_CIPHER_SPEC, tls_version(), and TLS_VERSION_TLS_1_3.

Referenced by tls_new_record().

◆ tls_new_alert()

int tls_new_alert ( struct tls_connection * tls,
struct io_buffer * iobuf )
static

Receive new Alert record.

Parameters
tlsTLS connection
iobufI/O buffer
Return values
rcReturn status code

Definition at line 2611 of file tls.c.

2612 {
2613 const struct {
2614 uint8_t level;
2615 uint8_t description;
2616 char next[0];
2617 } __attribute__ (( packed )) *alert = iobuf->data;
2618 size_t len = iob_len ( iobuf );
2619
2620 /* Sanity check */
2621 if ( sizeof ( *alert ) != len ) {
2622 DBGC ( tls, "TLS %p received overlength Alert\n", tls );
2623 DBGC_HD ( tls, alert, len );
2624 return -EINVAL_ALERT;
2625 }
2626 iob_pull ( iobuf, sizeof ( *alert ) );
2627
2628 /* Handle alert */
2629 switch ( alert->level ) {
2630 case TLS_ALERT_WARNING:
2631 switch ( alert->description ) {
2633 DBGC ( tls, "TLS %p closed by notification\n", tls );
2634 tls_close ( tls, 0 );
2635 break;
2636 default:
2637 DBGC ( tls, "TLS %p received warning alert %d\n",
2638 tls, alert->description );
2639 break;
2640 }
2641 return 0;
2642 case TLS_ALERT_FATAL:
2643 DBGC ( tls, "TLS %p received fatal alert %d\n",
2644 tls, alert->description );
2645 return -EPERM_ALERT;
2646 default:
2647 DBGC ( tls, "TLS %p received unknown alert level %d"
2648 "(alert %d)\n", tls, alert->level, alert->description );
2649 return -EIO_ALERT;
2650 }
2651}
#define EINVAL_ALERT
Definition tls.c:57
#define EPERM_ALERT
Definition tls.c:149
#define EIO_ALERT
Definition tls.c:89
#define TLS_ALERT_FATAL
Definition tls.h:104

References __attribute__, alert(), io_buffer::data, DBGC, DBGC_HD, EINVAL_ALERT, EIO_ALERT, EPERM_ALERT, iob_len(), iob_pull, len, next, TLS_ALERT_CLOSE_NOTIFY, TLS_ALERT_FATAL, TLS_ALERT_WARNING, and tls_close().

Referenced by tls_new_record().

◆ tls_new_hello_request()

int tls_new_hello_request ( struct tls_connection * tls,
const struct tls_cursor * cursor )
static

Receive new Hello Request handshake record.

Parameters
tlsTLS connection
cursorPlaintext handshake record
Return values
rcReturn status code

Definition at line 2660 of file tls.c.

2661 {
2663 int rc;
2664
2665 /* Parse HelloRequest structure */
2666 if ( ( rc = tls_parse ( tls_hello_request, tls->version, cursor,
2667 &request ) ) != 0 ) {
2668 DBGC ( tls, "TLS %p could not parse HelloRequest: %s\n",
2669 tls, strerror ( rc ) );
2670 return rc;
2671 }
2672
2673 /* Ignore if a handshake is in progress */
2674 if ( ! tls_ready ( tls ) ) {
2675 DBGC ( tls, "TLS %p ignoring Hello Request\n", tls );
2676 return 0;
2677 }
2678
2679 /* Fail unless server supports secure renegotiation */
2680 if ( ! ( tls->secure_renegotiation && tls->extended_master_secret ) ) {
2681 DBGC ( tls, "TLS %p refusing to renegotiate insecurely\n",
2682 tls );
2683 return -EPERM_RENEG_INSECURE;
2684 }
2685
2686 /* Restart negotiation */
2687 tls_restart ( tls );
2688
2689 return 0;
2690}
u8 request[0]
List of IEs requested.
Definition ieee80211.h:2
HelloRequest descriptor.
Definition tlsfmt.h:509
static int tls_ready(struct tls_connection *tls)
Determine if TLS connection is ready for application data.
Definition tls.c:272
static void tls_restart(struct tls_connection *tls)
Restart negotiation.
Definition tls.c:1875
#define EPERM_RENEG_INSECURE
Definition tls.c:157

References DBGC, EPERM_RENEG_INSECURE, tls_connection::extended_master_secret, rc, request, tls_connection::secure_renegotiation, strerror(), tls_parse, tls_ready(), tls_restart(), and tls_connection::version.

Referenced by tls_new_handshake().

◆ tls_new_server_hello()

int tls_new_server_hello ( struct tls_connection * tls,
const struct tls_cursor * cursor )
static

Receive new Server Hello handshake record.

Parameters
tlsTLS connection
cursorPlaintext handshake record
Return values
rcReturn status code

Definition at line 2699 of file tls.c.

2700 {
2701 struct tls_session *session = tls->session;
2702 struct tls_named_group *group;
2703 struct tls_server_hello hello;
2704 struct tls_renegotiation_info reneg;
2705 struct tls_supported_version supver;
2708 const uint8_t *key_map;
2710 uint16_t suite;
2711 size_t verify_len;
2712 int retry;
2713 int rc;
2714
2715 /* Parse ServerHello structure */
2716 if ( ( rc = tls_parse ( tls_server_hello, tls->version, cursor,
2717 &hello ) ) != 0 ) {
2718 DBGC ( tls, "TLS %p could not parse ServerHello: %s\n",
2719 tls, strerror ( rc ) );
2720 return rc;
2721 }
2722 random = container_of ( &hello.a->random[0], union tls_server_random,
2723 random[0] );
2724
2725 /* Parse RenegotiationInfo structure, if present */
2727 &hello.ext.reneg, &reneg ) ) != 0 ) {
2728 DBGC ( tls, "TLS %p could not parse RenegotiationInfo: %s\n",
2729 tls, strerror ( rc ) );
2730 return rc;
2731 }
2732
2733 /* Parse SupportedVersions structure, if present */
2735 &hello.ext.supver, &supver ) ) != 0 ) {
2736 DBGC ( tls, "TLS %p could not parse SupportedVersion: %s\n",
2737 tls, strerror ( rc ) );
2738 return rc;
2739 }
2740
2741 /* Parse KeyShareEntry, if present */
2742 retry = ( memcmp ( random, &tls_hrr_magic,
2743 sizeof ( *random ) ) == 0 );
2744 key_map = ( retry ? tls_key_share_hello_retry_request_map :
2745 tls_key_share_server_hello_map );
2746 if ( ( rc = tls_parse_opt_map ( key_map, tls->version,
2747 &hello.ext.key, key.desc ) ) != 0 ) {
2748 DBGC ( tls, "TLS %p could not parse KeyShare%s: %s\n",
2749 tls, ( retry ? "HelloRetryRequest" : "ServerHello" ),
2750 strerror ( rc ) );
2751 return rc;
2752 }
2753
2754 /* Refuse repeated retries */
2755 if ( retry && ( tls->suite != &tls_cipher_suite_null ) ) {
2756 DBGC ( tls, "TLS %p refusing repeated retry request\n", tls );
2757 return -EPROTO_RETRY;
2758 }
2759
2760 /* Handle secure renegotiation */
2761 if ( tls->secure_renegotiation ) {
2762
2763 /* Secure renegotiation is expected; verify data */
2764 verify_len = ( 2 * tls->verify.len );
2765 if ( ( reneg.verify.data == NULL ) ||
2766 ( reneg.verify.len != verify_len ) ||
2767 ( memcmp ( reneg.verify.data, tls->verify.dynamic,
2768 verify_len ) != 0 ) ) {
2769 DBGC ( tls, "TLS %p server failed secure "
2770 "renegotiation\n", tls );
2771 return -EPERM_RENEG_VERIFY;
2772 }
2773
2774 } else if ( reneg.verify.data != NULL ) {
2775
2776 /* Secure renegotiation is being enabled */
2777 if ( reneg.verify.len != 0 ) {
2778 DBGC ( tls, "TLS %p server provided non-empty initial "
2779 "renegotiation\n", tls );
2780 return -EPERM_RENEG_VERIFY;
2781 }
2782 tls->secure_renegotiation = 1;
2783 }
2784
2785 /* Select protocol version and cipher suite */
2786 version = ntohs ( supver.selected ? *supver.selected :
2787 hello.a->version );
2788 suite = hello.b->suite;
2789 if ( ( rc = tls_select_cipher ( tls, version, suite ) ) != 0 )
2790 return rc;
2791
2792 /* Check for downgrade attacks */
2794 ( tls->version < TLS_VERSION_MAX ) &&
2795 ( memcmp ( random->downgrade.magic, tls_downgrade_magic,
2796 sizeof ( random->downgrade.magic ) ) == 0 ) &&
2797 ( ( random->downgrade.version + TLS_VERSION_TLS_1_1 ) <
2798 TLS_VERSION_MAX ) ) {
2799 DBGC ( tls, "TLS %p detected downgrade attack:\n", tls );
2800 DBGC_HDA ( tls, 0, &random->downgrade,
2801 sizeof ( random->downgrade ) );
2802 return -EPERM_DOWNGRADE;
2803 }
2804
2805 /* Handle extended master secret */
2806 tls->extended_master_secret = ( !! hello.ext.ems.data );
2807
2808 /* Check session ID */
2809 if ( hello.session_id.len &&
2810 ( hello.session_id.len == session->id.len ) &&
2811 ( memcmp ( hello.session_id.data, session->id.data,
2812 hello.session_id.len ) == 0 ) ) {
2813
2814 /* Session ID match: resume session for TLSv1.2 or earlier */
2815 if ( ( ! tls_version ( tls, TLS_VERSION_TLS_1_3 ) ) &&
2816 ( rc = tls_resume ( tls ) ) != 0 ) {
2817 return rc;
2818 }
2819
2820 } else {
2821
2822 /* Session ID echo mismatch: abort for TLSv1.3 or later */
2823 if ( tls_version ( tls, TLS_VERSION_TLS_1_3 ) ) {
2824 DBGC ( tls, "TLS %p session ID mismatch\n", tls );
2825 DBGC_HDA ( tls, 0, hello.session_id.data,
2826 hello.session_id.len );
2827 return -EPERM_SESSION_ID;
2828 }
2829
2830 /* Record new session ID, if possible */
2831 if ( hello.session_id.len &&
2832 ( hello.session_id.len <= sizeof ( tls->new_id.data ) ) ){
2833 tls->new_id.len = hello.session_id.len;
2834 memcpy ( tls->new_id.data, hello.session_id.data,
2835 hello.session_id.len );
2836 }
2837 }
2838
2839 /* Select named group, if applicable */
2840 if ( key.group ) {
2841 group = tls_find_named_group ( *key.group );
2842 if ( ! group ) {
2843 DBGC ( tls, "TLS %p unsupported named group %d\n",
2844 tls, ntohs ( *key.group ) );
2845 return -ENOTSUP_GROUP;
2846 }
2847 tls->group = group;
2848 }
2849
2850 /* Agree shared key, if applicable */
2851 if ( ( ! retry ) && key.hello.public.data &&
2852 ( ( rc = tls_key_agree ( tls, tls->group,
2853 &key.hello.public ) ) != 0 ) ) {
2854 return rc;
2855 }
2856
2857 /* Record cookie, if any */
2858 if ( ( rc = tls_copy ( &hello.ext.cookie, &tls->cookie ) ) != 0 )
2859 return rc;
2860
2861 /* Retry ClientHello , if applicable */
2862 if ( is_pending ( &tls->client.negotiation ) && retry ) {
2863 tlskey_message ( &tls->key );
2865 tls_tx_resume ( tls );
2866 DBGC ( tls, "TLS %p retrying hello\n", tls );
2867 }
2868
2869 /* Schedule change to handshake traffic keys, if applicable */
2870 if ( tls_version ( tls, TLS_VERSION_TLS_1_3 ) && ( ! retry ) ) {
2873 }
2874
2875 return 0;
2876}
static char key_map[][128]
Definition pc_kbd.c:16
long int random(void)
Generate a pseudo-random number between 0 and 2147483647L or 2147483562?
Definition random.c:32
ServerHello descriptor.
Definition tlsfmt.h:595
SupportedVersions descriptor (in ServerHello).
Definition tlsfmt.h:680
static int tls_copy(const struct tls_cursor *src, struct tls_cursor *dst)
Duplicate content of a TLS cursor.
Definition tls.c:331
static int tls_resume(struct tls_connection *tls)
Resume session.
Definition tls.c:1824
static int tls_select_cipher(struct tls_connection *tls, unsigned int version, unsigned int cipher_suite)
Select protocol version and cipher suite.
Definition tls.c:744
static const uint8_t tls_downgrade_magic[7]
ServerHello downgrade magic value.
Definition tls.c:205
#define EPROTO_RETRY
Definition tls.c:193
#define EPERM_SESSION_ID
Definition tls.c:177
#define EPERM_DOWNGRADE
Definition tls.c:173
static int tls_key_agree(struct tls_connection *tls, struct tls_named_group *group, const struct tls_cursor *partner)
Agree shared secret.
Definition tls.c:1320
#define EPERM_RENEG_VERIFY
Definition tls.c:161
static const struct tls_random tls_hrr_magic
HelloRetryRequest magic value.
Definition tls.c:208
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.
Definition tlsfmt.c:343
#define tls_parse_opt(type, version, cursor, desc)
Parse optional TLS data structure.
Definition tlsfmt.h:748
const struct tls_phase tls_handshake
Handshake traffic phase.
Definition tlskey.c:144
void tlskey_message(struct tls_key_schedule *tlskey)
Replace running transcript digest with a message hash of itself.
Definition tlskey.c:457
KeyShareServerHello/KeyShareHelloRetryRequest combined descriptor.
Definition tlsfmt.h:542
TLS server random data.
Definition tls.h:57

References tls_rx::cipherspec, tls_tx::cipherspec, tls_connection::client, container_of, tls_connection::cookie, tls_cursor::data, tls_session_id::data, DBGC, DBGC_HDA, tls_verify_data::dynamic, ENOTSUP_GROUP, EPERM_DOWNGRADE, EPERM_RENEG_VERIFY, EPERM_SESSION_ID, EPROTO_RETRY, tls_connection::extended_master_secret, group, tls_connection::group, hello, tls_session::id, is_pending(), key, tls_connection::key, key_map, tls_cursor::len, tls_session_id::len, tls_verify_data::len, memcmp(), memcpy(), tls_client::negotiation, tls_connection::new_id, ntohs, NULL, tls_cipherspec::pending, tls_tx::pending, random(), rc, tls_connection::rx, tls_connection::secure_renegotiation, tls_supported_version::selected, tls_connection::session, strerror(), tls_connection::suite, tls_cipher_suite_null, tls_copy(), tls_downgrade_magic, tls_find_named_group(), tls_handshake, tls_hrr_magic, tls_key_agree(), tls_parse, tls_parse_opt, tls_parse_opt_map(), tls_resume(), tls_select_cipher(), TLS_TX_CLIENT_HELLO, tls_tx_resume(), tls_version(), TLS_VERSION_MAX, TLS_VERSION_TLS_1_1, TLS_VERSION_TLS_1_3, tlskey_message(), tls_connection::tx, tls_connection::verify, tls_renegotiation_info::verify, tls_connection::version, and version.

Referenced by tls_new_handshake().

◆ tls_new_session_ticket()

int tls_new_session_ticket ( struct tls_connection * tls,
const struct tls_cursor * cursor )
static

Receive New Session Ticket handshake record.

Parameters
tlsTLS connection
cursorPlaintext handshake record
Return values
rcReturn status code

Definition at line 2885 of file tls.c.

2886 {
2888 int rc;
2889
2890 /* Parse NewSessionTicket structure */
2891 if ( ( rc = tls_parse ( tls_new_session_ticket, tls->version,
2892 cursor, &ticket ) ) != 0 ) {
2893 DBGC ( tls, "TLS %p could not parse NewSessionTicket: %s\n",
2894 tls, strerror ( rc ) );
2895 return rc;
2896 }
2897
2898 /* Ignore as-yet unsupported session tickets */
2899 if ( tls_version ( tls, TLS_VERSION_TLS_1_3 ) ) {
2900 DBGC ( tls, "TLS %p ignoring unsupported New Session Ticket\n",
2901 tls );
2902 return 0;
2903 }
2904
2905 /* Record ticket */
2906 if ( ( rc = tls_copy ( &ticket.ticket, &tls->new_ticket ) ) != 0 )
2907 return rc;
2908
2909 return 0;
2910}
NewSessionTicket descriptor.
Definition tlsfmt.h:566
struct tls_cursor ticket
Ticket.
Definition tlsfmt.h:574

References DBGC, tls_connection::new_ticket, rc, strerror(), tls_new_session_ticket::ticket, tls_copy(), tls_parse, tls_version(), TLS_VERSION_TLS_1_3, and tls_connection::version.

◆ tls_new_certificate()

int tls_new_certificate ( struct tls_connection * tls,
const struct tls_cursor * cursor )
static

Receive new Certificate handshake record.

Parameters
tlsTLS connection
cursorPlaintext handshake record
Return values
rcReturn status code

Definition at line 2919 of file tls.c.

2920 {
2921 struct tls_certificate certificate;
2922 struct tls_certificate_entry entry;
2923 int rc;
2924
2925 /* Free any existing certificate chain */
2926 x509_chain_put ( tls->server.chain );
2927 tls->server.chain = NULL;
2928
2929 /* Create certificate chain */
2930 tls->server.chain = x509_alloc_chain();
2931 if ( ! tls->server.chain ) {
2932 rc = -ENOMEM_CHAIN;
2933 goto err_alloc_chain;
2934 }
2935
2936 /* Parse Certificate structure */
2937 if ( ( rc = tls_parse ( tls_certificate, tls->version, cursor,
2938 &certificate ) ) != 0 ) {
2939 DBGC ( tls, "TLS %p could not parse Certificate: %s\n",
2940 tls, strerror ( rc ) );
2941 goto err_certificate;
2942 }
2943
2944 /* Parse certificate list */
2945 for ( cursor = &certificate.list ; cursor->len ;
2946 cursor = &entry.next ) {
2947
2948 /* Parse CertificateEntry structure */
2949 if ( ( rc = tls_parse ( tls_certificate_entry, tls->version,
2950 cursor, &entry ) ) != 0 ) {
2951 DBGC ( tls, "TLS %p could not parse CertificateEntry: "
2952 "%s\n", tls, strerror ( rc ) );
2953 goto err_entry;
2954 }
2955
2956 /* Add certificate to chain */
2957 if ( ( rc = x509_append_raw ( tls->server.chain,
2958 entry.cert.data,
2959 entry.cert.len ) ) != 0 ) {
2960 DBGC ( tls, "TLS %p could not append certificate: "
2961 "%s\n", tls, strerror ( rc ) );
2962 goto err_append;
2963 }
2964 }
2965
2966 return 0;
2967
2968 err_append:
2969 err_entry:
2970 err_certificate:
2971 x509_chain_put ( tls->server.chain );
2972 tls->server.chain = NULL;
2973 err_alloc_chain:
2974 return rc;
2975}
#define ENOMEM_CHAIN
Definition tls.c:109
struct x509_chain * x509_alloc_chain(void)
Allocate X.509 certificate chain.
Definition x509.c:1615
int x509_append_raw(struct x509_chain *chain, const void *data, size_t len)
Append X.509 certificate to X.509 certificate chain.
Definition x509.c:1674

References tls_certificate_entry::cert, tls_server::chain, tls_cursor::data, DBGC, ENOMEM_CHAIN, tls_cursor::len, tls_certificate::list, tls_certificate_entry::next, NULL, rc, tls_connection::server, strerror(), tls_parse, tls_connection::version, x509_alloc_chain(), x509_append_raw(), and x509_chain_put().

Referenced by tls_new_handshake().

◆ tls_verify_signature()

int tls_verify_signature ( struct tls_connection * tls,
const struct tls_cursor * cursor,
const struct tls_cursor * params )
static

Verify a signature record.

Parameters
tlsTLS connection
cursorSignature record
paramsAdditional parameters
Return values
rcReturn status code

Definition at line 2985 of file tls.c.

2987 {
2988 struct tls_signature_hash_algorithm *sig_hash;
2990 struct tls_digitally_signed dsig;
2991 struct x509_certificate *cert;
2992 int rc;
2993
2994 /* Parse DigitallySigned structure */
2995 if ( ( rc = tls_parse ( tls_digitally_signed, tls->version,
2996 cursor, &dsig ) ) != 0 ) {
2997 DBGC ( tls, "TLS %p could not parse DigitallySigned: %s\n",
2998 tls, strerror ( rc ) );
2999 return rc;
3000 }
3001
3002 /* Identify server certificate */
3003 if ( ! tls->server.chain ) {
3004 DBGC ( tls, "TLS %p has no server certificate chain\n", tls );
3005 return -ENOENT_CERT;
3006 }
3007 cert = x509_first ( tls->server.chain );
3008 if ( ! cert ) {
3009 DBGC ( tls, "TLS %p has no server certificate\n", tls );
3010 return -ENOENT_CERT;
3011 }
3012
3013 /* Identify signature and hash algorithm */
3014 if ( tls_version ( tls, TLS_VERSION_TLS_1_2 ) ) {
3015
3016 /* TLSv1.2 and above use explicit algorithm identifiers */
3017 assert ( dsig.sig_hash != NULL );
3018 sig_hash = tls_find_signature_hash ( *dsig.sig_hash );
3019 if ( ! sig_hash ) {
3020 DBGC ( tls, "TLS %p unsupported signature hash "
3021 "%#04x\n", tls, ntohs ( *dsig.sig_hash ) );
3022 return -ENOTSUP_SIG_HASH;
3023 }
3024
3025 } else {
3026
3027 /* TLSv1.1 and below use fixed algorithms */
3028 assert ( dsig.sig_hash == NULL );
3029 sig_hash = &tmp;
3030 memset ( sig_hash, 0, sizeof ( *sig_hash ) );
3031 sig_hash->pubkey = cert->subject.public_key.algorithm->pubkey;
3032 sig_hash->digest = ( ( sig_hash->pubkey == &rsa_algorithm ) ?
3034 }
3035
3036 /* Verify signature */
3037 if ( ( rc = tls_hash_verify ( tls, sig_hash, cert, params,
3038 tls_asn1 ( &dsig.sig ) ) ) != 0 ) {
3039 return rc;
3040 }
3041
3042 return 0;
3043}
static int tls_hash_verify(struct tls_connection *tls, struct tls_signature_hash_algorithm *sig_hash, struct x509_certificate *cert, const struct tls_cursor *params, const struct asn1_cursor *sig)
Verify signature over parameters used to construct shared secret.
Definition tls.c:1472
static struct tls_signature_hash_algorithm * tls_find_signature_hash(unsigned int code)
Find TLS signature and hash algorithm.
Definition tls.c:1041
static const struct asn1_cursor * tls_asn1(const struct tls_cursor *cursor)
Get ASN.1 cursor from TLS cursor.
Definition tlsfmt.h:698

References x509_public_key::algorithm, assert, tls_server::chain, DBGC, tls_signature_hash_algorithm::digest, ENOENT_CERT, ENOTSUP_SIG_HASH, md5_sha1_algorithm, memset(), ntohs, NULL, asn1_algorithm::pubkey, tls_signature_hash_algorithm::pubkey, x509_subject::public_key, rc, rsa_algorithm, tls_connection::server, sha1_algorithm, tls_digitally_signed::sig, tls_digitally_signed::sig_hash, strerror(), x509_certificate::subject, tls_asn1(), tls_find_signature_hash(), tls_hash_verify(), tls_parse, tls_version(), TLS_VERSION_TLS_1_2, tmp, tls_connection::version, and x509_first().

Referenced by tls_new_certificate_verify(), and tls_new_server_key_exchange().

◆ tls_new_certificate_verify()

int tls_new_certificate_verify ( struct tls_connection * tls,
const struct tls_cursor * cursor )
static

Receive new Certificate Verify handshake record.

Parameters
tlsTLS connection
cursorPlaintext handshake record
Return values
rcReturn status code

Definition at line 3052 of file tls.c.

3053 {
3054 static const struct tls_cursor params;
3055 int rc;
3056
3057 /* Verify signature */
3058 if ( ( rc = tls_verify_signature ( tls, cursor, &params ) ) != 0 )
3059 return rc;
3060
3061 return 0;
3062}
static int tls_verify_signature(struct tls_connection *tls, const struct tls_cursor *cursor, const struct tls_cursor *params)
Verify a signature record.
Definition tls.c:2985

References rc, and tls_verify_signature().

Referenced by tls_new_handshake().

◆ tls_new_server_key_exchange()

int tls_new_server_key_exchange ( struct tls_connection * tls,
const struct tls_cursor * cursor )
static

Receive new Server Key Exchange handshake record.

Parameters
tlsTLS connection
cursorPlaintext handshake record
Return values
rcReturn status code

Definition at line 3071 of file tls.c.

3072 {
3073 struct tls_cipher_suite *suite = tls->suite;
3074 struct tls_key_exchange_parameters kex;
3075 struct tls_cursor params;
3076 struct tls_cursor dsig;
3077 int rc;
3078
3079 /* Parse parameters */
3080 if ( ( rc = suite->exchange->parse ( tls, cursor, &kex ) ) != 0 )
3081 return rc;
3082 DBGC ( tls, "TLS %p using named group %s-%s\n",
3083 tls, suite->exchange->name, kex.group->exchange->name );
3084
3085 /* Signature follows key exchange parameters */
3086 assert ( kex.len <= cursor->len );
3087 params.data = cursor->data;
3088 params.len = kex.len;
3089 dsig.data = ( cursor->data + kex.len );
3090 dsig.len = ( cursor->len - kex.len );
3091
3092 /* Generate pre-master secret */
3093 if ( ( rc = tls_key_agree ( tls, kex.group, &kex.partner ) ) != 0 )
3094 return rc;
3095
3096 /* Verify signature (immediately follows parameters) */
3097 if ( ( rc = tls_verify_signature ( tls, &dsig, &params ) ) != 0 )
3098 return rc;
3099
3100 /* Record named group */
3101 tls->group = kex.group;
3102
3103 return 0;
3104}
int(* parse)(struct tls_connection *tls, const struct tls_cursor *cursor, struct tls_key_exchange_parameters *kex)
Parse key exchange parameters from Server Key Exchange record.
Definition tls.h:251
TLS key exchange parameters.
Definition tls.h:228

References assert, tls_cursor::data, DBGC, tls_cipher_suite::exchange, tls_named_group::exchange, tls_connection::group, tls_key_exchange_parameters::group, tls_cursor::len, tls_key_exchange_parameters::len, exchange_algorithm::name, tls_key_exchange_algorithm::name, tls_key_exchange_algorithm::parse, tls_key_exchange_parameters::partner, rc, tls_connection::suite, tls_key_agree(), and tls_verify_signature().

Referenced by tls_new_handshake().

◆ tls_new_certificate_request()

int tls_new_certificate_request ( struct tls_connection * tls,
const struct tls_cursor *cursor __unused )
static

Receive new Certificate Request handshake record.

Parameters
tlsTLS connection
cursorPlaintext handshake record
lenLength of plaintext handshake record
Return values
rcReturn status code

Definition at line 3115 of file tls.c.

3116 {
3117 struct x509_certificate *cert;
3118 int rc;
3119
3120 /* We can only send a single certificate, so there is no point
3121 * in parsing the Certificate Request.
3122 */
3123
3124 /* Free any existing client certificate chain */
3125 x509_chain_put ( tls->client.chain );
3126 tls->client.chain = NULL;
3127
3128 /* Create client certificate chain */
3129 tls->client.chain = x509_alloc_chain();
3130 if ( ! tls->client.chain ) {
3131 rc = -ENOMEM;
3132 goto err_alloc;
3133 }
3134
3135 /* Determine client certificate to be sent, if any */
3136 cert = x509_find_key ( NULL, tls->client.key );
3137 if ( cert ) {
3138 DBGC ( tls, "TLS %p selected client certificate %s\n",
3139 tls, x509_name ( cert ) );
3140
3141 /* Append client certificate to chain */
3142 if ( ( rc = x509_append ( tls->client.chain, cert ) ) != 0 )
3143 goto err_append;
3144
3145 /* Append any relevant issuer certificates */
3146 if ( ( rc = x509_auto_append ( tls->client.chain,
3147 &certstore ) ) != 0 )
3148 goto err_auto_append;
3149 } else {
3150
3151 /* Send an empty certificate chain */
3152 DBGC ( tls, "TLS %p could not find certificate corresponding "
3153 "to private key\n", tls );
3154 }
3155
3156 return 0;
3157
3158 err_auto_append:
3159 err_append:
3160 x509_chain_put ( tls->client.chain );
3161 tls->client.chain = NULL;
3162 err_alloc:
3163 return rc;
3164}
struct x509_chain certstore
Certificate store.
Definition certstore.c:90
int x509_auto_append(struct x509_chain *chain, struct x509_chain *store)
Append X.509 certificates to X.509 certificate chain.
Definition x509.c:1888
struct x509_certificate * x509_find_key(struct x509_chain *store, struct private_key *key)
Identify X.509 certificate by corresponding public key.
Definition x509.c:1855
int x509_append(struct x509_chain *chain, struct x509_certificate *cert)
Append X.509 certificate to X.509 certificate chain.
Definition x509.c:1638

References __unused, certstore, tls_client::chain, tls_connection::client, DBGC, ENOMEM, tls_client::key, NULL, rc, x509_alloc_chain(), x509_append(), x509_auto_append(), x509_chain_put(), x509_find_key(), and x509_name().

Referenced by tls_new_handshake().

◆ tls_new_server_hello_done()

int tls_new_server_hello_done ( struct tls_connection * tls,
const struct tls_cursor * cursor )
static

Receive new Server Hello Done handshake record.

Parameters
tlsTLS connection
cursorPlaintext handshake record
Return values
rcReturn status code

Definition at line 3173 of file tls.c.

3174 {
3176 int rc;
3177
3178 /* Parse ServerHelloDone structure */
3179 if ( ( rc = tls_parse ( tls_server_hello_done, tls->version, cursor,
3180 &done ) ) != 0 ) {
3181 DBGC ( tls, "TLS %p could not parse ServerHelloDone: %s\n",
3182 tls, strerror ( rc ) );
3183 return rc;
3184 }
3185
3186 /* End of certificate-based handshake: start validation */
3187 if ( ( rc = tls_validator_start ( tls ) ) != 0 )
3188 return rc;
3189
3190 return 0;
3191}
struct bofm_section_header done
Definition bofm_test.c:46
ServerHelloDone descriptor.
Definition tlsfmt.h:630
static int tls_validator_start(struct tls_connection *tls)
Start certificate validation.
Definition tls.c:4437

References DBGC, done, rc, strerror(), tls_parse, tls_validator_start(), and tls_connection::version.

Referenced by tls_new_handshake().

◆ tls_new_finished()

int tls_new_finished ( struct tls_connection * tls,
const struct tls_cursor * cursor )
static

Receive new Finished handshake record.

Parameters
tlsTLS connection
cursorPlaintext handshake record
Return values
rcReturn status code

Definition at line 3200 of file tls.c.

3201 {
3202 int rc;
3203
3204 /* Confirm peer identity */
3205 if ( ( rc = channel_confirm ( &tls->channel, cursor->data,
3206 cursor->len ) ) != 0 ) {
3207 DBGC ( tls, "TLS %p could not confirm peer identity: %s\n",
3208 tls, strerror ( rc ) );
3209 return rc;
3210 }
3211
3212 /* Mark server as finished */
3213 pending_put ( &tls->server.negotiation );
3214
3215 /* Handle key schedule */
3216 if ( tls_version ( tls, TLS_VERSION_TLS_1_3 ) ) {
3217
3218 /* Generate master secret */
3219 if ( ( rc = tlskey_master ( &tls->key, 1 ) ) != 0 ) {
3220 DBGC ( tls, "TLS %p could not generate master secret: "
3221 "%s\n", tls, strerror ( rc ) );
3222 return rc;
3223 }
3224
3225 /* Schedule change to application traffic keys */
3227 }
3228
3229 /* Handle state transitions */
3230 if ( tls_version ( tls, TLS_VERSION_TLS_1_3 ) && tls->server.chain ) {
3231
3232 /* End of certificate-based handshake: start validation */
3233 if ( ( rc = tls_validator_start ( tls ) ) != 0 )
3234 return rc;
3235
3236 } else if ( is_pending ( &tls->client.negotiation ) ) {
3237
3238 /* Resuming session: trigger sending Finished */
3239 if ( ! tls_version ( tls, TLS_VERSION_TLS_1_3 ) )
3241 tls->tx.pending |= TLS_TX_FINISHED;
3242 tls_tx_resume ( tls );
3243
3244 } else {
3245
3246 /* Client has already finished: establish session */
3247 if ( ( rc = tls_establish ( tls ) ) != 0 )
3248 return rc;
3249 }
3250
3251 return 0;
3252}
int channel_confirm(struct secure_channel *channel, const void *auth, size_t len)
Confirm peer identity.
Definition channel.c:896
@ TLS_TX_FINISHED
Definition tls.h:224
@ TLS_TX_CHANGE_CIPHER
Definition tls.h:223

References tls_server::chain, tls_connection::channel, channel_confirm(), tls_rx::cipherspec, tls_connection::client, tls_cursor::data, DBGC, is_pending(), tls_connection::key, tls_cursor::len, tls_client::negotiation, tls_server::negotiation, tls_cipherspec::pending, tls_tx::pending, pending_put(), rc, tls_connection::rx, tls_connection::server, strerror(), tls_application, tls_establish(), TLS_TX_CHANGE_CIPHER, TLS_TX_FINISHED, tls_tx_resume(), tls_validator_start(), tls_version(), TLS_VERSION_TLS_1_3, tlskey_master(), and tls_connection::tx.

Referenced by tls_new_handshake().

◆ tls_new_handshake()

int tls_new_handshake ( struct tls_connection * tls,
struct io_buffer * iobuf )
static

Receive new Handshake record.

Parameters
tlsTLS connection
iobufI/O buffer
Return values
rcReturn status code

Following the general robustness principle, we accept handshake records in any order of arrival and rely on the secure channel abstraction to determine whether or not the resulting sequence of operations is sufficient to establish the channel.

Most non-standard handshake record sequences would not manage to successfully establish the channel. For example: a premature Finished that attempts to skip the ServerKeyExchange would fail because the channel will reject an attempt to confirm an unbound peer identity.

It would be possible for an inventive server to construct non-standard sequences of handshake records that do successfully establish the secure channel. For example: a server could choose to send a second ServerKeyExchange record with a second valid signature (over the updated transcript digest that includes the first ServerKeyExchange). This would be non-standard and rather pointless, but would be accepted for the purpose of establishing the secure channel since it does in fact provide the required security properties.

Definition at line 3282 of file tls.c.

3283 {
3284 int ( * handler ) ( struct tls_connection *tls,
3285 const struct tls_cursor *cursor );
3286 const union tls_handshake_header *handshake;
3287 struct tls_cursor cursor;
3288 size_t remaining;
3289 size_t len;
3290 int rc;
3291
3292 while ( ( remaining = iob_len ( iobuf ) ) ) {
3293
3294 /* Fail if receive cipher has changed mid-record */
3295 if ( tls->rx.cipherspec.pending ) {
3296 DBGC ( tls, "TLS %p cipher change mid-record\n", tls );
3297 return -EPROTO_CIPHER_CHANGE;
3298 }
3299
3300 /* Parse header */
3301 if ( remaining < sizeof ( *handshake ) ) {
3302 /* Leave remaining fragment unconsumed */
3303 break;
3304 }
3305 handshake = iobuf->data;
3306 cursor.data = ( iobuf->data + sizeof ( *handshake ) );
3307 cursor.len = TLS_HANDSHAKE_LEN ( handshake->type_len );
3308 len = ( cursor.len + sizeof ( *handshake ) );
3309 if ( remaining < len ) {
3310 /* Leave remaining fragment unconsumed */
3311 break;
3312 }
3313
3314 /* Identify handshake type */
3315 switch ( handshake->type ) {
3316 case TLS_HELLO_REQUEST:
3317 handler = tls_new_hello_request;
3318 break;
3319 case TLS_SERVER_HELLO:
3320 handler = tls_new_server_hello;
3321 break;
3323 handler = tls_new_session_ticket;
3324 break;
3325 case TLS_CERTIFICATE:
3326 handler = tls_new_certificate;
3327 break;
3330 break;
3333 break;
3336 break;
3338 handler = tls_new_server_hello_done;
3339 break;
3340 case TLS_FINISHED:
3341 handler = tls_new_finished;
3342 break;
3343 default:
3344 DBGC ( tls, "TLS %p ignoring handshake type %d\n",
3345 tls, handshake->type );
3346 handler = NULL;
3347 break;
3348 }
3349
3350 /* Handle handshake */
3351 if ( handler && ( ( rc = handler ( tls, &cursor ) ) != 0 ) )
3352 return rc;
3353
3354 /* Add to handshake digest (except for Hello Requests,
3355 * which are explicitly excluded).
3356 */
3357 if ( handshake->type != TLS_HELLO_REQUEST )
3358 tls_add_handshake ( tls, handshake, len );
3359
3360 /* Move to next handshake record */
3361 iob_pull ( iobuf, len );
3362 }
3363
3364 return 0;
3365}
static int tls_new_certificate_verify(struct tls_connection *tls, const struct tls_cursor *cursor)
Receive new Certificate Verify handshake record.
Definition tls.c:3052
static int tls_new_hello_request(struct tls_connection *tls, const struct tls_cursor *cursor)
Receive new Hello Request handshake record.
Definition tls.c:2660
static int tls_new_finished(struct tls_connection *tls, const struct tls_cursor *cursor)
Receive new Finished handshake record.
Definition tls.c:3200
static int tls_new_certificate_request(struct tls_connection *tls, const struct tls_cursor *cursor __unused)
Receive new Certificate Request handshake record.
Definition tls.c:3115
static int tls_new_server_key_exchange(struct tls_connection *tls, const struct tls_cursor *cursor)
Receive new Server Key Exchange handshake record.
Definition tls.c:3071
static int tls_new_certificate(struct tls_connection *tls, const struct tls_cursor *cursor)
Receive new Certificate handshake record.
Definition tls.c:2919
static int tls_new_server_hello_done(struct tls_connection *tls, const struct tls_cursor *cursor)
Receive new Server Hello Done handshake record.
Definition tls.c:3173
static int tls_new_server_hello(struct tls_connection *tls, const struct tls_cursor *cursor)
Receive new Server Hello handshake record.
Definition tls.c:2699
#define TLS_SERVER_HELLO
Definition tls.h:92
#define TLS_SERVER_KEY_EXCHANGE
Definition tls.h:95
#define TLS_NEW_SESSION_TICKET
Definition tls.h:93
#define TLS_HANDSHAKE_LEN(type_len)
Get TLS handshake length.
Definition tls.h:54
#define TLS_HELLO_REQUEST
Definition tls.h:90
#define TLS_CERTIFICATE_REQUEST
Definition tls.h:96
#define TLS_SERVER_HELLO_DONE
Definition tls.h:97

References tls_rx::cipherspec, io_buffer::data, tls_cursor::data, DBGC, EPROTO_CIPHER_CHANGE, iob_len(), iob_pull, len, tls_cursor::len, NULL, tls_cipherspec::pending, rc, tls_connection::rx, tls_add_handshake(), TLS_CERTIFICATE, TLS_CERTIFICATE_REQUEST, TLS_CERTIFICATE_VERIFY, TLS_FINISHED, TLS_HANDSHAKE_LEN, TLS_HELLO_REQUEST, tls_new_certificate(), tls_new_certificate_request(), tls_new_certificate_verify(), tls_new_finished(), tls_new_hello_request(), tls_new_server_hello(), tls_new_server_hello_done(), tls_new_server_key_exchange(), TLS_NEW_SESSION_TICKET, TLS_SERVER_HELLO, TLS_SERVER_HELLO_DONE, TLS_SERVER_KEY_EXCHANGE, tls_handshake_header::type, and tls_handshake_header::type_len.

Referenced by tls_new_record().

◆ tls_new_unknown()

int tls_new_unknown ( struct tls_connection *tls __unused,
struct io_buffer * iobuf )
static

Receive new unknown record.

Parameters
tlsTLS connection
iobufI/O buffer
Return values
rcReturn status code

Definition at line 3374 of file tls.c.

3375 {
3376
3377 /* RFC4346 says that we should just ignore unknown record types */
3378 iob_pull ( iobuf, iob_len ( iobuf ) );
3379 return 0;
3380}

References __unused, iob_len(), and iob_pull.

Referenced by tls_new_record().

◆ tls_new_data()

int tls_new_data ( struct tls_connection * tls,
struct list_head * rx_data )
static

Receive new data record.

Parameters
tlsTLS connection
rx_dataList of received data buffers
Return values
rcReturn status code

Definition at line 3389 of file tls.c.

3390 {
3391 struct io_buffer *iobuf;
3392 int rc;
3393
3394 /* Fail unless we are ready to receive data */
3395 if ( ! tls_ready ( tls ) )
3396 return -ENOTCONN;
3397
3398 /* Deliver each I/O buffer in turn */
3399 while ( ( iobuf = list_first_entry ( rx_data, struct io_buffer,
3400 list ) ) ) {
3401 list_del ( &iobuf->list );
3402 if ( ( rc = xfer_deliver_iob ( &tls->plainstream,
3403 iobuf ) ) != 0 ) {
3404 DBGC ( tls, "TLS %p could not deliver data: "
3405 "%s\n", tls, strerror ( rc ) );
3406 return rc;
3407 }
3408 }
3409
3410 return 0;
3411}
#define ENOTCONN
The socket is not connected.
Definition errno.h:613
#define list_first_entry(list, type, member)
Get the container of the first entry in a list.
Definition list.h:334

References DBGC, ENOTCONN, io_buffer::list, list_del, list_first_entry, tls_connection::plainstream, rc, strerror(), tls_ready(), and xfer_deliver_iob().

Referenced by tls_new_record().

◆ tls_new_record()

int tls_new_record ( struct tls_connection * tls,
unsigned int type,
struct list_head * rx_data )
static

Receive new record.

Parameters
tlsTLS connection
typeRecord type
rx_dataList of received data buffers
Return values
rcReturn status code

Definition at line 3421 of file tls.c.

3422 {
3423 int ( * handler ) ( struct tls_connection *tls,
3424 struct io_buffer *iobuf );
3425 struct io_buffer *tmp = NULL;
3426 struct io_buffer **iobuf;
3427 int rc;
3428
3429 /* Deliver data records as-is to the plainstream interface */
3430 if ( type == TLS_TYPE_DATA )
3431 return tls_new_data ( tls, rx_data );
3432
3433 /* Determine handler and fragment buffer */
3434 iobuf = &tmp;
3435 switch ( type ) {
3437 handler = tls_new_change_cipher;
3438 break;
3439 case TLS_TYPE_ALERT:
3440 handler = tls_new_alert;
3441 break;
3442 case TLS_TYPE_HANDSHAKE:
3443 handler = tls_new_handshake;
3444 iobuf = &tls->rx.handshake;
3445 break;
3446 default:
3447 DBGC ( tls, "TLS %p unknown record type %d\n", tls, type );
3448 handler = tls_new_unknown;
3449 break;
3450 }
3451
3452 /* Merge into a single I/O buffer */
3453 if ( *iobuf )
3454 list_add ( &(*iobuf)->list, rx_data );
3455 *iobuf = iob_concatenate ( rx_data );
3456 if ( ! *iobuf ) {
3457 DBGC ( tls, "TLS %p could not concatenate non-data record "
3458 "type %d\n", tls, type );
3460 goto err_concatenate;
3461 }
3462
3463 /* Handle record */
3464 if ( ( rc = handler ( tls, *iobuf ) ) != 0 )
3465 goto err_handle;
3466
3467 /* Discard I/O buffer if empty */
3468 if ( ! iob_len ( *iobuf ) ) {
3469 free_iob ( *iobuf );
3470 *iobuf = NULL;
3471 }
3472
3473 /* Sanity check */
3474 assert ( tmp == NULL );
3475
3476 return 0;
3477
3478 err_handle:
3479 free_iob ( *iobuf );
3480 *iobuf = NULL;
3481 err_concatenate:
3482 return rc;
3483}
struct io_buffer * iob_concatenate(struct list_head *list)
Concatenate I/O buffers into a single buffer.
Definition iobuf.c:250
static int tls_new_change_cipher(struct tls_connection *tls, struct io_buffer *iobuf)
Receive new Change Cipher record.
Definition tls.c:2581
#define ENOMEM_RX_CONCAT
Definition tls.c:125
static int tls_new_unknown(struct tls_connection *tls __unused, struct io_buffer *iobuf)
Receive new unknown record.
Definition tls.c:3374
static int tls_new_data(struct tls_connection *tls, struct list_head *rx_data)
Receive new data record.
Definition tls.c:3389
static int tls_new_handshake(struct tls_connection *tls, struct io_buffer *iobuf)
Receive new Handshake record.
Definition tls.c:3282
static int tls_new_alert(struct tls_connection *tls, struct io_buffer *iobuf)
Receive new Alert record.
Definition tls.c:2611

References assert, DBGC, ENOMEM_RX_CONCAT, free_iob(), tls_rx::handshake, iob_concatenate(), iob_len(), list_add, NULL, rc, tls_connection::rx, tls_new_alert(), tls_new_change_cipher(), tls_new_data(), tls_new_handshake(), tls_new_unknown(), TLS_TYPE_ALERT, TLS_TYPE_CHANGE_CIPHER, TLS_TYPE_DATA, TLS_TYPE_HANDSHAKE, tmp, and type.

Referenced by tls_new_ciphertext().

◆ tls_hmac_init()

void tls_hmac_init ( struct tls_cipherspec * cipherspec,
void * ctx,
struct tls_auth_header * authhdr )
static

Initialise HMAC.

Parameters
cipherspecCipher specification
ctxContext
authhdrAuthentication header

Definition at line 3499 of file tls.c.

3500 {
3501 struct tls_cipher_suite *suite = cipherspec->suite;
3502 struct digest_algorithm *digest = suite->digest;
3503
3504 hmac_init ( digest, ctx, cipherspec->mac_secret, suite->mac_len );
3505 hmac_update ( digest, ctx, authhdr, sizeof ( *authhdr ) );
3506}
struct golan_eq_context ctx
Definition CIB_PRM.h:0
void hmac_init(struct digest_algorithm *digest, void *ctx, const void *secret, size_t len)
Initialise HMAC.
Definition hmac.c:106
static void hmac_update(struct digest_algorithm *digest, void *ctx, const void *data, size_t len)
Update HMAC.
Definition hmac.h:62

References ctx, tls_cipher_suite::digest, hmac_init(), hmac_update(), tls_cipher_suite::mac_len, tls_cipherspec::mac_secret, and tls_cipherspec::suite.

Referenced by tls_hmac(), and tls_hmac_list().

◆ tls_hmac_update()

void tls_hmac_update ( struct tls_cipherspec * cipherspec,
void * ctx,
const void * data,
size_t len )
static

Update HMAC.

Parameters
cipherspecCipher specification
ctxContext
dataData
lenLength of data

Definition at line 3516 of file tls.c.

3517 {
3518 struct digest_algorithm *digest = cipherspec->suite->digest;
3519
3520 hmac_update ( digest, ctx, data, len );
3521}

References ctx, data, tls_cipher_suite::digest, hmac_update(), len, and tls_cipherspec::suite.

Referenced by tls_hmac(), and tls_hmac_list().

◆ tls_hmac_final()

void tls_hmac_final ( struct tls_cipherspec * cipherspec,
void * ctx,
void * hmac )
static

Finalise HMAC.

Parameters
cipherspecCipher specification
ctxContext
macHMAC to fill in

Definition at line 3530 of file tls.c.

3531 {
3532 struct digest_algorithm *digest = cipherspec->suite->digest;
3533
3534 hmac_final ( digest, ctx, hmac );
3535}
void hmac_final(struct digest_algorithm *digest, void *ctx, void *hmac)
Finalise HMAC.
Definition hmac.c:124

References ctx, tls_cipher_suite::digest, hmac_final(), and tls_cipherspec::suite.

Referenced by tls_hmac(), and tls_hmac_list().

◆ tls_hmac()

void tls_hmac ( struct tls_cipherspec * cipherspec,
struct tls_auth_header * authhdr,
const void * data,
size_t len,
void * hmac )
static

Calculate HMAC.

Parameters
cipherspecCipher specification
authhdrAuthentication header
dataData
lenLength of data
macHMAC to fill in

Definition at line 3546 of file tls.c.

3548 {
3549 struct digest_algorithm *digest = cipherspec->suite->digest;
3550 uint8_t ctx[ hmac_ctxsize ( digest ) ];
3551
3552 tls_hmac_init ( cipherspec, ctx, authhdr );
3553 tls_hmac_update ( cipherspec, ctx, data, len );
3554 tls_hmac_final ( cipherspec, ctx, hmac );
3555}
static size_t hmac_ctxsize(struct digest_algorithm *digest)
Calculate HMAC context size.
Definition hmac.h:48
static void tls_hmac_init(struct tls_cipherspec *cipherspec, void *ctx, struct tls_auth_header *authhdr)
Initialise HMAC.
Definition tls.c:3499
static void tls_hmac_final(struct tls_cipherspec *cipherspec, void *ctx, void *hmac)
Finalise HMAC.
Definition tls.c:3530
static void tls_hmac_update(struct tls_cipherspec *cipherspec, void *ctx, const void *data, size_t len)
Update HMAC.
Definition tls.c:3516

References ctx, data, tls_cipher_suite::digest, hmac_ctxsize(), len, tls_cipherspec::suite, tls_hmac_final(), tls_hmac_init(), and tls_hmac_update().

Referenced by tls_send_record().

◆ tls_hmac_list()

void tls_hmac_list ( struct tls_cipherspec * cipherspec,
struct tls_auth_header * authhdr,
struct list_head * list,
void * hmac )
static

Calculate HMAC over list of I/O buffers.

Parameters
cipherspecCipher specification
authhdrAuthentication header
listList of I/O buffers
macHMAC to fill in

Definition at line 3565 of file tls.c.

3567 {
3568 struct digest_algorithm *digest = cipherspec->suite->digest;
3569 uint8_t ctx[ hmac_ctxsize ( digest ) ];
3570 struct io_buffer *iobuf;
3571
3572 tls_hmac_init ( cipherspec, ctx, authhdr );
3573 list_for_each_entry ( iobuf, list, list ) {
3574 tls_hmac_update ( cipherspec, ctx, iobuf->data,
3575 iob_len ( iobuf ) );
3576 }
3577 tls_hmac_final ( cipherspec, ctx, hmac );
3578}

References ctx, io_buffer::data, tls_cipher_suite::digest, hmac_ctxsize(), iob_len(), io_buffer::list, list_for_each_entry, tls_cipherspec::suite, tls_hmac_final(), tls_hmac_init(), and tls_hmac_update().

Referenced by tls_new_ciphertext().

◆ tls_iob_reserved()

size_t tls_iob_reserved ( struct tls_connection * tls,
size_t len )
static

Calculate maximum additional length required for transmitted record(s).

Parameters
tlsTLS connection
lenI/O buffer payload length
Return values
reserveMaximum additional length to reserve

Definition at line 3587 of file tls.c.

3587 {
3588 struct tls_cipherspec *cipherspec = &tls->tx.cipherspec;
3589 struct tls_cipher_suite *suite = cipherspec->suite;
3590 struct secure_pipe *pipe = &tls->channel.tx;
3591 struct cipher_algorithm *cipher = pipe->cipher;
3592 struct tls_header *tlshdr;
3593 uint8_t *inner_type;
3594 unsigned int count;
3595 size_t each;
3596
3597 /* Calculate number of records (allowing for zero-length records) */
3598 count = ( len ?
3599 ( ( len + TLS_TX_BUFSIZE - 1 ) / TLS_TX_BUFSIZE ) : 1 );
3600
3601 /* Calculate maximum additional length per record */
3602 each = ( sizeof ( *tlshdr ) + suite->record_iv_len +
3603 sizeof ( *inner_type ) + suite->mac_len +
3604 ( is_block_cipher ( cipher ) ? cipher->blocksize : 0 ) +
3605 cipher->authsize );
3606
3607 /* Calculate maximum total additional length */
3608 return ( count * each );
3609}
static unsigned int count
Number of entries.
Definition dwmac.h:220

References cipher_algorithm::authsize, cipher_algorithm::blocksize, tls_connection::channel, secure_pipe::cipher, tls_tx::cipherspec, count, is_block_cipher(), len, tls_cipher_suite::mac_len, tls_cipher_suite::record_iv_len, tls_cipherspec::suite, TLS_TX_BUFSIZE, secure_channel::tx, and tls_connection::tx.

Referenced by tls_alloc_iob(), and tls_send_record().

◆ tls_verify_padding()

int tls_verify_padding ( struct tls_connection * tls,
struct io_buffer * iobuf )
static

Verify block padding.

Parameters
tlsTLS connection
iobufLast received I/O buffer
Return values
lenPadding length, or negative error
rcReturn status code

Definition at line 3854 of file tls.c.

3855 {
3856 uint8_t *padding;
3857 unsigned int pad;
3858 unsigned int i;
3859 size_t len;
3860
3861 /* Extract and verify padding */
3862 padding = ( iobuf->tail - 1 );
3863 pad = *padding;
3864 len = ( pad + 1 );
3865 if ( len > iob_len ( iobuf ) ) {
3866 DBGC ( tls, "TLS %p received underlength padding\n", tls );
3867 DBGC_HD ( tls, iobuf->data, iob_len ( iobuf ) );
3868 return -EINVAL_PADDING;
3869 }
3870 for ( i = 0 ; i < pad ; i++ ) {
3871 if ( *(--padding) != pad ) {
3872 DBGC ( tls, "TLS %p received bad padding\n", tls );
3873 DBGC_HD ( tls, iobuf->data, iob_len ( iobuf ) );
3874 return -EINVAL_PADDING;
3875 }
3876 }
3877
3878 return len;
3879}
u32 pad[9]
Padding.
Definition ar9003_mac.h:23
#define EINVAL_PADDING
Definition tls.c:65

References io_buffer::data, DBGC, DBGC_HD, EINVAL_PADDING, iob_len(), len, pad, and io_buffer::tail.

Referenced by tls_new_ciphertext().

◆ tls_extract_inner()

int tls_extract_inner ( struct tls_connection * tls,
int type,
struct list_head * rx_data )
static

Extract inner plaintext.

Parameters
tlsTLS connection
typeRecord type
rx_dataList of received data buffers
Return values
typeInner plaintext record type, or negative error

Definition at line 3889 of file tls.c.

3890 {
3891 struct io_buffer *iobuf;
3892 const uint8_t *data;
3893 size_t len;
3894
3895 /* Check outer record type */
3896 if ( type != TLS_TYPE_DATA ) {
3897 DBGC ( tls, "TLS %p invalid outer type %d\n", tls, type );
3898 return -EINVAL_INNER;
3899 }
3900
3901 /* Strip trailing zero padding and obtain inner type */
3902 type = 0;
3903 list_for_each_entry_reverse ( iobuf, rx_data, list ) {
3904 len = iob_len ( iobuf );
3905 data = iobuf->data;
3906 while ( len && ( ! type ) )
3907 type = data[--len];
3908 iob_unput ( iobuf, ( iob_len ( iobuf ) - len ) );
3909 if ( type )
3910 break;
3911 }
3912
3913 /* Fail if no inner type was detected */
3914 if ( ! type ) {
3915 DBGC ( tls, "TLS %p missing inner type\n", tls );
3916 return -EINVAL_INNER;
3917 }
3918
3919 return type;
3920}
#define list_for_each_entry_reverse(pos, head, member)
Iterate over entries in a list in reverse order.
Definition list.h:445
#define EINVAL_INNER
Definition tls.c:81

References data, io_buffer::data, DBGC, EINVAL_INNER, iob_len(), iob_unput, len, io_buffer::list, list_for_each_entry_reverse, TLS_TYPE_DATA, and type.

Referenced by tls_new_ciphertext().

◆ tls_new_ciphertext()

int tls_new_ciphertext ( struct tls_connection * tls,
struct tls_header * tlshdr,
struct list_head * rx_data )
static

Receive new ciphertext record.

Parameters
tlsTLS connection
tlshdrRecord header
rx_dataList of received data buffers
Return values
rcReturn status code

Definition at line 3930 of file tls.c.

3932 {
3933 struct tls_cipherspec *cipherspec = &tls->rx.cipherspec;
3934 struct tls_cipher_suite *suite = cipherspec->suite;
3935 struct digest_algorithm *digest = suite->digest;
3936 struct secure_pipe *pipe = &tls->channel.rx;
3937 struct cipher_algorithm *cipher = pipe->cipher;
3938 int type = tlshdr->type;
3939 size_t len = ntohs ( tlshdr->length );
3940 struct {
3941 uint8_t fixed[suite->fixed_iv_len];
3942 uint8_t record[suite->record_iv_len];
3943 } __attribute__ (( packed )) iv;
3944 struct tls_auth_header authhdr;
3945 uint8_t verify_mac[digest->digestsize];
3946 uint8_t verify_auth[cipher->authsize];
3947 struct io_buffer *first;
3948 struct io_buffer *last;
3949 struct io_buffer *iobuf;
3950 void *mac;
3951 void *auth;
3952 size_t check_len;
3953 int pad_len;
3954 int rc;
3955
3956 /* Sanity check */
3957 assert ( cipher == suite->cipher );
3958
3959 /* Handle TLS version 1.3 Change Cipher records */
3960 if ( tls_version ( tls, TLS_VERSION_TLS_1_3 ) &&
3961 ( type == TLS_TYPE_CHANGE_CIPHER ) ) {
3962 /* TLS version 1.3 allows unencrypted Change Cipher
3963 * records to be sent after switching to use the
3964 * handshake traffic keys. This is an ugly protocol
3965 * hack to work around badly implemented firewalls of
3966 * the kind beloved by large organisations.
3967 *
3968 * Process these as plaintext records. Change Cipher
3969 * records are ignored for TLS version 1.3, so this is
3970 * just the most convenient way to discard the
3971 * records.
3972 */
3973 return tls_new_record ( tls, type, rx_data );
3974 }
3975
3976 /* Locate first and last data buffers */
3977 assert ( ! list_empty ( rx_data ) );
3978 first = list_first_entry ( rx_data, struct io_buffer, list );
3979 last = list_last_entry ( rx_data, struct io_buffer, list );
3980
3981 /* Construct authentication data */
3982 authhdr.seq = cpu_to_be64 ( cipherspec->seq++ );
3983 authhdr.header.type = tlshdr->type;
3984 authhdr.header.version = tlshdr->version;
3985 authhdr.header.length = htons ( len );
3986
3987 /* Extract initialisation vector */
3988 if ( iob_len ( first ) < sizeof ( iv.record ) ) {
3989 DBGC ( tls, "TLS %p received underlength IV\n", tls );
3990 DBGC_HD ( tls, first->data, iob_len ( first ) );
3991 return -EINVAL_IV;
3992 }
3993 memcpy ( iv.fixed, cipherspec->fixed_iv, sizeof ( iv.fixed ) );
3994 if ( suite->flags & TLS_CIPHER_FL_SEQUENTIAL_IV ) {
3995 memset ( iv.record, 0, sizeof ( iv.record ) );
3996 assert ( sizeof ( iv ) >= sizeof ( authhdr.seq ) );
3997 tls_xor ( ( ( ( void * ) &iv ) + sizeof ( iv ) -
3998 sizeof ( authhdr.seq ) ), &authhdr.seq,
3999 sizeof ( authhdr.seq ) );
4000 }
4001 memcpy ( iv.record, first->data, sizeof ( iv.record ) );
4002 iob_pull ( first, sizeof ( iv.record ) );
4003 len -= sizeof ( iv.record );
4004
4005 /* Extract unencrypted authentication tag */
4006 if ( iob_len ( last ) < cipher->authsize ) {
4007 DBGC ( tls, "TLS %p received underlength authentication tag\n",
4008 tls );
4009 DBGC_HD ( tls, last->data, iob_len ( last ) );
4010 return -EINVAL_MAC;
4011 }
4012 iob_unput ( last, cipher->authsize );
4013 len -= cipher->authsize;
4014 auth = last->tail;
4015
4016 /* Check that overall length is a multiple of the cipher blocksize */
4017 assert ( ( TLS_RX_BUFSIZE % cipher->blocksize ) == 0 );
4018 if ( iob_len ( last ) & ( cipher->blocksize - 1 ) ) {
4019 DBGC ( tls, "TLS %p invalid received length %zd\n",
4020 tls, len );
4021 return -EINVAL_BLOCK;
4022 }
4023
4024 /* Set initialisation vector */
4025 if ( ( rc = cipher_setiv ( cipher, pipe->ctx, &iv,
4026 sizeof ( iv ) ) ) != 0 ) {
4027 DBGC ( tls, "TLS %p could not set RX IV: %s\n",
4028 tls, strerror ( rc ) );
4029 return rc;
4030 }
4031
4032 /* Process authentication data, if applicable */
4033 if ( is_auth_cipher ( cipher ) ) {
4034 if ( tls_version ( tls, TLS_VERSION_TLS_1_3 ) ) {
4035 cipher_decrypt ( cipher, pipe->ctx, &authhdr.header,
4036 NULL, sizeof ( authhdr.header ) );
4037 } else {
4038 authhdr.header.length = htons ( len );
4039 cipher_decrypt ( cipher, pipe->ctx, &authhdr,
4040 NULL, sizeof ( authhdr ) );
4041 }
4042 }
4043
4044 /* Decrypt the received data */
4045 check_len = 0;
4046 list_for_each_entry ( iobuf, &tls->rx.data, list ) {
4047 cipher_decrypt ( cipher, pipe->ctx,
4048 iobuf->data, iobuf->data, iob_len ( iobuf ) );
4049 check_len += iob_len ( iobuf );
4050 }
4051 assert ( check_len == len );
4052
4053 /* Strip block padding, if applicable */
4054 if ( is_block_cipher ( cipher ) ) {
4055 pad_len = tls_verify_padding ( tls, last );
4056 if ( pad_len < 0 ) {
4057 /* Assume zero padding length to avoid timing attacks */
4058 pad_len = 0;
4059 }
4060 iob_unput ( last, pad_len );
4061 len -= pad_len;
4062 }
4063
4064 /* Extract decrypted MAC */
4065 if ( iob_len ( last ) < suite->mac_len ) {
4066 DBGC ( tls, "TLS %p received underlength MAC\n", tls );
4067 DBGC_HD ( tls, last->data, iob_len ( last ) );
4068 return -EINVAL_MAC;
4069 }
4070 iob_unput ( last, suite->mac_len );
4071 len -= suite->mac_len;
4072 mac = last->tail;
4073
4074 /* Dump received data */
4075 DBGC2 ( tls, "Received plaintext data:\n" );
4076 check_len = 0;
4077 list_for_each_entry ( iobuf, rx_data, list ) {
4078 DBGC2_HD ( tls, iobuf->data, iob_len ( iobuf ) );
4079 check_len += iob_len ( iobuf );
4080 }
4081 assert ( check_len == len );
4082
4083 /* Generate MAC */
4084 authhdr.header.length = htons ( len );
4085 if ( suite->mac_len )
4086 tls_hmac_list ( cipherspec, &authhdr, rx_data, verify_mac );
4087
4088 /* Generate authentication tag */
4089 cipher_auth ( cipher, pipe->ctx, verify_auth );
4090
4091 /* Verify MAC */
4092 if ( memcmp ( mac, verify_mac, suite->mac_len ) != 0 ) {
4093 DBGC ( tls, "TLS %p failed MAC verification\n", tls );
4094 return -EINVAL_MAC;
4095 }
4096
4097 /* Verify authentication tag */
4098 if ( memcmp ( auth, verify_auth, cipher->authsize ) != 0 ) {
4099 DBGC ( tls, "TLS %p failed authentication tag verification\n",
4100 tls );
4101 return -EINVAL_MAC;
4102 }
4103
4104 /* Extract inner plaintext, if applicable */
4105 if ( ( tls_has_inner ( tls, cipher ) ) &&
4106 ( ( type = tls_extract_inner ( tls, type, rx_data ) ) < 0 ) ) {
4107 rc = type;
4108 return rc;
4109 }
4110
4111 /* Process plaintext record */
4112 if ( ( rc = tls_new_record ( tls, type, rx_data ) ) != 0 )
4113 return rc;
4114
4115 /* Handle any pending traffic phase changes */
4116 if ( ( rc = tls_pending_cipher ( tls, &tls->tx.cipherspec ) ) != 0 )
4117 return rc;
4118 if ( ( rc = tls_pending_cipher ( tls, &tls->rx.cipherspec ) ) != 0 )
4119 return rc;
4120
4121 return 0;
4122}
#define DBGC2_HD(...)
Definition compiler.h:549
#define cipher_decrypt(cipher, ctx, src, dst, len)
Definition crypto.h:336
#define list_last_entry(list, type, member)
Get the container of the last entry in a list.
Definition list.h:347
uint32_t first
First block in range.
Definition pccrr.h:1
#define EINVAL_IV
Definition tls.c:61
#define EINVAL_BLOCK
Definition tls.c:85
static void tls_hmac_list(struct tls_cipherspec *cipherspec, struct tls_auth_header *authhdr, struct list_head *list, void *hmac)
Calculate HMAC over list of I/O buffers.
Definition tls.c:3565
static int tls_extract_inner(struct tls_connection *tls, int type, struct list_head *rx_data)
Extract inner plaintext.
Definition tls.c:3889
#define EINVAL_MAC
Definition tls.c:73
static int tls_verify_padding(struct tls_connection *tls, struct io_buffer *iobuf)
Verify block padding.
Definition tls.c:3854
static int tls_pending_cipher(struct tls_connection *tls, struct tls_cipherspec *cipherspec)
Apply pending traffic phase change (if any).
Definition tls.c:980
static int tls_new_record(struct tls_connection *tls, unsigned int type, struct list_head *rx_data)
Receive new record.
Definition tls.c:3421
#define TLS_RX_BUFSIZE
RX I/O buffer size.
Definition tls.h:546

References __attribute__, assert, cipher_algorithm::authsize, cipher_algorithm::blocksize, tls_connection::channel, secure_pipe::cipher, tls_cipher_suite::cipher, cipher_auth(), cipher_decrypt, cipher_setiv(), tls_rx::cipherspec, tls_tx::cipherspec, cpu_to_be64, secure_pipe::ctx, io_buffer::data, tls_rx::data, DBGC, DBGC2, DBGC2_HD, DBGC_HD, tls_cipher_suite::digest, digest_algorithm::digestsize, EINVAL_BLOCK, EINVAL_IV, EINVAL_MAC, first, fixed, tls_cipherspec::fixed_iv, tls_cipher_suite::fixed_iv_len, tls_cipher_suite::flags, tls_auth_header::header, htons, iob_len(), iob_pull, iob_unput, is_auth_cipher(), is_block_cipher(), iv, len, tls_header::length, io_buffer::list, list_empty, list_first_entry, list_for_each_entry, list_last_entry, mac, tls_cipher_suite::mac_len, memcmp(), memcpy(), memset(), ntohs, NULL, rc, tls_cipher_suite::record_iv_len, secure_channel::rx, tls_connection::rx, tls_auth_header::seq, tls_cipherspec::seq, strerror(), tls_cipherspec::suite, io_buffer::tail, TLS_CIPHER_FL_SEQUENTIAL_IV, tls_extract_inner(), tls_has_inner(), tls_hmac_list(), tls_new_record(), tls_pending_cipher(), TLS_RX_BUFSIZE, TLS_TYPE_CHANGE_CIPHER, tls_verify_padding(), tls_version(), TLS_VERSION_TLS_1_3, tls_xor(), tls_connection::tx, tls_header::type, type, and tls_header::version.

Referenced by tls_newdata_process_data().

◆ tls_plainstream_window()

size_t tls_plainstream_window ( struct tls_connection * tls)
static

Check flow control window.

Parameters
tlsTLS connection
Return values
lenLength of window

Definition at line 4137 of file tls.c.

4137 {
4138
4139 /* Block window unless we are ready to accept data */
4140 if ( ! tls_ready ( tls ) )
4141 return 0;
4142
4143 return xfer_window ( &tls->cipherstream );
4144}
size_t xfer_window(struct interface *intf)
Check flow control window.
Definition xfer.c:117

References tls_connection::cipherstream, tls_ready(), and xfer_window().

◆ tls_plainstream_deliver()

int tls_plainstream_deliver ( struct tls_connection * tls,
struct io_buffer * iobuf,
struct xfer_metadata *meta __unused )
static

Deliver datagram as raw data.

Parameters
tlsTLS connection
iobufI/O buffer
metaData transfer metadata
Return values
rcReturn status code

Definition at line 4154 of file tls.c.

4156 {
4157 int rc;
4158
4159 /* Refuse unless we are ready to accept data */
4160 if ( ! tls_ready ( tls ) ) {
4161 rc = -ENOTCONN;
4162 goto done;
4163 }
4164
4165 /* Send data record */
4166 if ( ( rc = tls_send_record ( tls, TLS_TYPE_DATA,
4167 iob_disown ( iobuf ) ) ) != 0 )
4168 goto done;
4169
4170 done:
4171 free_iob ( iobuf );
4172 return rc;
4173}

References __unused, done, ENOTCONN, free_iob(), iob_disown, meta, rc, tls_ready(), tls_send_record(), and TLS_TYPE_DATA.

◆ tls_progress()

int tls_progress ( struct tls_connection * tls,
struct job_progress * progress )
static

Report job progress.

Parameters
tlsTLS connection
progressProgress report to fill in
Return values
ongoing_rcOngoing job status code (if known)

Definition at line 4182 of file tls.c.

4183 {
4184
4185 /* Return cipherstream or validator progress as applicable */
4186 if ( is_pending ( &tls->server.validation ) ) {
4187 return job_progress ( &tls->server.validator, progress );
4188 } else {
4189 return job_progress ( &tls->cipherstream, progress );
4190 }
4191}
int job_progress(struct interface *intf, struct job_progress *progress)
Get job progress.
Definition job.c:44

References tls_connection::cipherstream, is_pending(), job_progress(), tls_connection::server, tls_server::validation, and tls_server::validator.

◆ tls_newdata_process_header()

int tls_newdata_process_header ( struct tls_connection * tls)
static

Handle received TLS header.

Parameters
tlsTLS connection
Return values
rcReturned status code

Definition at line 4222 of file tls.c.

4222 {
4223 struct tls_cipherspec *cipherspec = &tls->rx.cipherspec;
4224 struct secure_pipe *pipe = &tls->channel.rx;
4225 struct cipher_algorithm *cipher = pipe->cipher;
4226 size_t iv_len = cipherspec->suite->record_iv_len;
4227 size_t data_len = ntohs ( tls->rx.header.length );
4228 size_t remaining = data_len;
4229 size_t frag_len;
4230 size_t reserve;
4231 struct io_buffer *iobuf;
4232 struct io_buffer *tmp;
4233 int rc;
4234
4235 /* Sanity check */
4236 assert ( ( TLS_RX_BUFSIZE % cipher->alignsize ) == 0 );
4237
4238 /* Calculate alignment reservation at start of first data buffer */
4239 reserve = ( ( -iv_len ) & ( cipher->alignsize - 1 ) );
4240 remaining += reserve;
4241
4242 /* Allocate data buffers now that we know the length */
4243 assert ( list_empty ( &tls->rx.data ) );
4244 do {
4245
4246 /* Calculate fragment length. Ensure that no block is
4247 * smaller than TLS_RX_MIN_BUFSIZE (by increasing the
4248 * allocation length if necessary).
4249 */
4250 frag_len = remaining;
4251 if ( frag_len > TLS_RX_BUFSIZE )
4252 frag_len = TLS_RX_BUFSIZE;
4253 remaining -= frag_len;
4254 if ( remaining < TLS_RX_MIN_BUFSIZE ) {
4255 frag_len += remaining;
4256 remaining = 0;
4257 }
4258
4259 /* Allocate buffer */
4260 iobuf = alloc_iob_raw ( frag_len, TLS_RX_ALIGN, 0 );
4261 if ( ! iobuf ) {
4262 DBGC ( tls, "TLS %p could not allocate %zd of %zd "
4263 "bytes for receive buffer\n", tls,
4264 remaining, data_len );
4265 rc = -ENOMEM_RX_DATA;
4266 goto err;
4267 }
4268
4269 /* Ensure tailroom is exactly what we asked for. This
4270 * will result in unaligned I/O buffers when the
4271 * fragment length is unaligned, which can happen only
4272 * before we switch to using a block cipher.
4273 */
4274 iob_reserve ( iobuf, ( iob_tailroom ( iobuf ) - frag_len ) );
4275
4276 /* Ensure first buffer length will be aligned to a
4277 * multiple of the cipher alignment size after
4278 * stripping the record IV.
4279 */
4280 iob_reserve ( iobuf, reserve );
4281 reserve = 0;
4282
4283 /* Add I/O buffer to list */
4284 list_add_tail ( &iobuf->list, &tls->rx.data );
4285
4286 } while ( remaining );
4287 assert ( ! list_empty ( &tls->rx.data ) );
4288
4289 /* Move to data state */
4290 tls->rx.state = TLS_RX_DATA;
4291
4292 return 0;
4293
4294 err:
4295 list_for_each_entry_safe ( iobuf, tmp, &tls->rx.data, list ) {
4296 list_del ( &iobuf->list );
4297 free_iob ( iobuf );
4298 }
4299 return rc;
4300}
struct io_buffer * alloc_iob_raw(size_t len, size_t align, size_t offset)
Allocate I/O buffer with specified alignment and offset.
Definition iobuf.c:49
static size_t iob_tailroom(struct io_buffer *iobuf)
Calculate available space at end of an I/O buffer.
Definition iobuf.h:240
size_t alignsize
Alignment size.
Definition crypto.h:80
enum tls_rx_state state
State machine current state.
Definition tls.h:442
struct tls_header header
Current received record header.
Definition tls.h:444
#define ENOMEM_RX_DATA
Definition tls.c:121
#define TLS_RX_MIN_BUFSIZE
Minimum RX I/O buffer size.
Definition tls.h:554
#define TLS_RX_ALIGN
RX I/O buffer alignment.
Definition tls.h:557
@ TLS_RX_DATA
Definition tls.h:214
uint32_t data_len
Microcode data size (or 0 to indicate 2000 bytes).
Definition ucode.h:15

References cipher_algorithm::alignsize, alloc_iob_raw(), assert, tls_connection::channel, secure_pipe::cipher, tls_rx::cipherspec, tls_rx::data, data_len, DBGC, ENOMEM_RX_DATA, free_iob(), tls_rx::header, iob_reserve, iob_tailroom(), tls_header::length, io_buffer::list, list_add_tail, list_del, list_empty, list_for_each_entry_safe, ntohs, rc, tls_cipher_suite::record_iv_len, secure_channel::rx, tls_connection::rx, tls_rx::state, tls_cipherspec::suite, TLS_RX_ALIGN, TLS_RX_BUFSIZE, TLS_RX_DATA, TLS_RX_MIN_BUFSIZE, and tmp.

Referenced by tls_cipherstream_deliver().

◆ tls_newdata_process_data()

int tls_newdata_process_data ( struct tls_connection * tls)
static

Handle received TLS data payload.

Parameters
tlsTLS connection
Return values
rcReturned status code

Definition at line 4308 of file tls.c.

4308 {
4309 struct io_buffer *iobuf;
4310 int rc;
4311
4312 /* Move current buffer to end of list */
4313 iobuf = list_first_entry ( &tls->rx.data, struct io_buffer, list );
4314 list_del ( &iobuf->list );
4315 list_add_tail ( &iobuf->list, &tls->rx.data );
4316
4317 /* Continue receiving data if any space remains */
4318 iobuf = list_first_entry ( &tls->rx.data, struct io_buffer, list );
4319 if ( iob_tailroom ( iobuf ) )
4320 return 0;
4321
4322 /* Process record */
4323 if ( ( rc = tls_new_ciphertext ( tls, &tls->rx.header,
4324 &tls->rx.data ) ) != 0 )
4325 return rc;
4326
4327 /* Return to header state */
4328 assert ( list_empty ( &tls->rx.data ) );
4329 tls->rx.state = TLS_RX_HEADER;
4330 iob_unput ( &tls->rx.iobuf, sizeof ( tls->rx.header ) );
4331
4332 return 0;
4333}
struct io_buffer iobuf
Current received record header (static I/O buffer).
Definition tls.h:446
static int tls_new_ciphertext(struct tls_connection *tls, struct tls_header *tlshdr, struct list_head *rx_data)
Receive new ciphertext record.
Definition tls.c:3930
@ TLS_RX_HEADER
Definition tls.h:213

References assert, tls_rx::data, tls_rx::header, iob_tailroom(), iob_unput, tls_rx::iobuf, io_buffer::list, list_add_tail, list_del, list_empty, list_first_entry, rc, tls_connection::rx, tls_rx::state, tls_new_ciphertext(), and TLS_RX_HEADER.

Referenced by tls_cipherstream_deliver().

◆ tls_cipherstream_window()

size_t tls_cipherstream_window ( struct tls_connection * tls)
static

Check flow control window.

Parameters
tlsTLS connection
Return values
lenLength of window

Definition at line 4341 of file tls.c.

4341 {
4342
4343 /* Open window until we are ready to accept data */
4344 if ( ! tls_ready ( tls ) )
4345 return -1UL;
4346
4347 return xfer_window ( &tls->plainstream );
4348}

References tls_connection::plainstream, tls_ready(), and xfer_window().

◆ tls_cipherstream_deliver()

int tls_cipherstream_deliver ( struct tls_connection * tls,
struct io_buffer * iobuf,
struct xfer_metadata *xfer __unused )
static

Receive new ciphertext.

Parameters
tlsTLS connection
iobufI/O buffer
metaData transfer metadat
Return values
rcReturn status code

Definition at line 4358 of file tls.c.

4360 {
4361 size_t frag_len;
4362 int ( * process ) ( struct tls_connection *tls );
4363 struct io_buffer *dest;
4364 int rc;
4365
4366 while ( iob_len ( iobuf ) ) {
4367
4368 /* Select buffer according to current state */
4369 switch ( tls->rx.state ) {
4370 case TLS_RX_HEADER:
4371 dest = &tls->rx.iobuf;
4373 break;
4374 case TLS_RX_DATA:
4375 dest = list_first_entry ( &tls->rx.data,
4376 struct io_buffer, list );
4377 assert ( dest != NULL );
4379 break;
4380 default:
4381 assert ( 0 );
4383 goto done;
4384 }
4385
4386 /* Copy data portion to buffer */
4387 frag_len = iob_len ( iobuf );
4388 if ( frag_len > iob_tailroom ( dest ) )
4389 frag_len = iob_tailroom ( dest );
4390 memcpy ( iob_put ( dest, frag_len ), iobuf->data, frag_len );
4391 iob_pull ( iobuf, frag_len );
4392
4393 /* Process data if buffer is now full */
4394 if ( iob_tailroom ( dest ) == 0 ) {
4395 if ( ( rc = process ( tls ) ) != 0 ) {
4396 tls_close_alert ( tls, rc );
4397 goto done;
4398 }
4399 }
4400 }
4401 rc = 0;
4402
4403 done:
4404 free_iob ( iobuf );
4405 return rc;
4406}
if(len >=6 *4) __asm__ __volatile__("movsl" if(len >=5 *4) __asm__ __volatile__("movsl" if(len >=4 *4) __asm__ __volatile__("movsl" if(len >=3 *4) __asm__ __volatile__("movsl" if(len >=2 *4) __asm__ __volatile__("movsl" if(len >=1 *4) __asm__ __volatile__("movsl" if((len % 4) >=2) __asm__ __volatile__("movsw" if((len % 2) >=1) __asm__ __volatile__("movsb" retur dest)
Definition string.h:151
A process.
Definition process.h:18
#define EINVAL_RX_STATE
Definition tls.c:69
static int tls_newdata_process_data(struct tls_connection *tls)
Handle received TLS data payload.
Definition tls.c:4308
static int tls_newdata_process_header(struct tls_connection *tls)
Handle received TLS header.
Definition tls.c:4222
static void tls_close_alert(struct tls_connection *tls, int rc)
Send closure alert and finish with TLS connection.
Definition tls.c:482

References __unused, assert, io_buffer::data, tls_rx::data, dest, done, EINVAL_RX_STATE, free_iob(), iob_len(), iob_pull, iob_put, iob_tailroom(), tls_rx::iobuf, io_buffer::list, list_first_entry, memcpy(), NULL, rc, tls_connection::rx, tls_rx::state, tls_close_alert(), tls_newdata_process_data(), tls_newdata_process_header(), TLS_RX_DATA, and TLS_RX_HEADER.

◆ tls_validator_done()

void tls_validator_done ( struct tls_connection * tls,
int rc )
static

Handle certificate validation completion.

Parameters
tlsTLS connection
rcReason for completion

Definition at line 4465 of file tls.c.

4465 {
4466
4467 /* Mark validation as complete */
4468 pending_put ( &tls->server.validation );
4469
4470 /* Close validator interface */
4471 intf_restart ( &tls->server.validator, rc );
4472
4473 /* Check for validation failure */
4474 if ( rc != 0 ) {
4475 DBGC ( tls, "TLS %p certificate validation failed: %s\n",
4476 tls, strerror ( rc ) );
4477 goto err;
4478 }
4479 DBGC ( tls, "TLS %p certificate validation succeeded\n", tls );
4480
4481 /* Schedule transmission of applicable handshake messages */
4482 if ( tls->client.chain ) {
4484 if ( ! list_empty ( &tls->client.chain->links ) )
4486 }
4487 if ( ! tls_version ( tls, TLS_VERSION_TLS_1_3 ) ) {
4490 }
4491 tls->tx.pending |= TLS_TX_FINISHED;
4492 tls_tx_resume ( tls );
4493
4494 return;
4495
4496 err:
4497 tls_close_alert ( tls, rc );
4498 return;
4499}
void intf_restart(struct interface *intf, int rc)
Shut down and restart an object interface.
Definition interface.c:344
@ TLS_TX_CLIENT_KEY_EXCHANGE
Definition tls.h:221
@ TLS_TX_CERTIFICATE_VERIFY
Definition tls.h:222
@ TLS_TX_CERTIFICATE
Definition tls.h:220

References tls_client::chain, tls_connection::client, DBGC, intf_restart(), x509_chain::links, list_empty, tls_tx::pending, pending_put(), rc, tls_connection::server, strerror(), tls_close_alert(), TLS_TX_CERTIFICATE, TLS_TX_CERTIFICATE_VERIFY, TLS_TX_CHANGE_CIPHER, TLS_TX_CLIENT_KEY_EXCHANGE, TLS_TX_FINISHED, tls_tx_resume(), tls_version(), TLS_VERSION_TLS_1_3, tls_connection::tx, tls_server::validation, and tls_server::validator.

◆ tls_tx_step()

void tls_tx_step ( struct tls_connection * tls)
static

TLS TX state machine.

Parameters
tlsTLS connection

Definition at line 4523 of file tls.c.

4523 {
4524 struct tls_session *session = tls->session;
4525 struct tls_connection *conn;
4526 int rc;
4527
4528 /* Wait for cipherstream to become ready */
4529 if ( ! xfer_window ( &tls->cipherstream ) )
4530 return;
4531
4532 /* Send first pending transmission */
4533 if ( tls->tx.pending & TLS_TX_CLIENT_HELLO ) {
4534 /* Serialise server negotiations within a session, to
4535 * provide a consistent view of session IDs and
4536 * session tickets.
4537 */
4538 list_for_each_entry ( conn, &session->conn, list ) {
4539 if ( conn == tls )
4540 break;
4541 if ( is_pending ( &conn->server.negotiation ) )
4542 return;
4543 }
4544 /* Send Client Hello */
4545 if ( ( rc = tls_send_client_hello ( tls ) ) != 0 ) {
4546 DBGC ( tls, "TLS %p could not send Client Hello: %s\n",
4547 tls, strerror ( rc ) );
4548 goto err;
4549 }
4551 } else if ( tls->tx.pending & TLS_TX_CERTIFICATE ) {
4552 /* Send Certificate */
4553 if ( ( rc = tls_send_certificate ( tls ) ) != 0 ) {
4554 DBGC ( tls, "TLS %p could not send Certificate: %s\n",
4555 tls, strerror ( rc ) );
4556 goto err;
4557 }
4559 } else if ( tls->tx.pending & TLS_TX_CLIENT_KEY_EXCHANGE ) {
4560 /* Send Client Key Exchange */
4561 if ( ( rc = tls_send_client_key_exchange ( tls ) ) != 0 ) {
4562 DBGC ( tls, "TLS %p could not send Client Key "
4563 "Exchange: %s\n", tls, strerror ( rc ) );
4564 goto err;
4565 }
4567 } else if ( tls->tx.pending & TLS_TX_CERTIFICATE_VERIFY ) {
4568 /* Send Certificate Verify */
4569 if ( ( rc = tls_send_certificate_verify ( tls ) ) != 0 ) {
4570 DBGC ( tls, "TLS %p could not send Certificate "
4571 "Verify: %s\n", tls, strerror ( rc ) );
4572 goto err;
4573 }
4575 } else if ( tls->tx.pending & TLS_TX_CHANGE_CIPHER ) {
4576 /* Send Change Cipher */
4577 if ( ( rc = tls_send_change_cipher ( tls ) ) != 0 ) {
4578 DBGC ( tls, "TLS %p could not send Change Cipher: "
4579 "%s\n", tls, strerror ( rc ) );
4580 goto err;
4581 }
4583 } else if ( tls->tx.pending & TLS_TX_FINISHED ) {
4584 /* Send Finished */
4585 if ( ( rc = tls_send_finished ( tls ) ) != 0 ) {
4586 DBGC ( tls, "TLS %p could not send Finished: %s\n",
4587 tls, strerror ( rc ) );
4588 goto err;
4589 }
4590 tls->tx.pending &= ~TLS_TX_FINISHED;
4591 }
4592
4593 /* Reschedule process if pending transmissions remain,
4594 * otherwise send notification of a window change.
4595 */
4596 if ( tls->tx.pending ) {
4597 tls_tx_resume ( tls );
4598 } else {
4600 }
4601
4602 return;
4603
4604 err:
4605 tls_close_alert ( tls, rc );
4606}
static int tls_send_certificate(struct tls_connection *tls)
Transmit Certificate record.
Definition tls.c:2201
static int tls_send_finished(struct tls_connection *tls)
Transmit Finished record.
Definition tls.c:2486
static int tls_send_client_hello(struct tls_connection *tls)
Transmit Client Hello record.
Definition tls.c:2190
static int tls_send_client_key_exchange(struct tls_connection *tls)
Transmit Client Key Exchange record.
Definition tls.c:2286
static int tls_send_change_cipher(struct tls_connection *tls)
Transmit Change Cipher record.
Definition tls.c:2456
static int tls_send_certificate_verify(struct tls_connection *tls)
Transmit Certificate Verify record.
Definition tls.c:2359

References tls_connection::cipherstream, tls_session::conn, DBGC, is_pending(), tls_connection::list, list_for_each_entry, tls_server::negotiation, tls_tx::pending, tls_connection::plainstream, rc, tls_connection::server, tls_connection::session, strerror(), tls_close_alert(), tls_send_certificate(), tls_send_certificate_verify(), tls_send_change_cipher(), tls_send_client_hello(), tls_send_client_key_exchange(), tls_send_finished(), TLS_TX_CERTIFICATE, TLS_TX_CERTIFICATE_VERIFY, TLS_TX_CHANGE_CIPHER, TLS_TX_CLIENT_HELLO, TLS_TX_CLIENT_KEY_EXCHANGE, TLS_TX_FINISHED, tls_tx_resume(), tls_connection::tx, xfer_window(), and xfer_window_changed().

◆ add_tls()

int add_tls ( struct interface * xfer,
const char * name,
struct x509_root * root,
struct private_key * key )

Add TLS on an interface.

Parameters
xferData transfer interface
nameHost name
rootRoot of trust (or NULL to use default)
keyPrivate key (or NULL to use default)
Return values
rcReturn status code

Definition at line 4628 of file tls.c.

4629 {
4630 struct tls_connection *tls;
4631 int rc;
4632
4633 /* Allocate and initialise TLS structure */
4634 tls = malloc ( sizeof ( *tls ) );
4635 if ( ! tls ) {
4636 rc = -ENOMEM;
4637 goto err_alloc;
4638 }
4639 memset ( tls, 0, sizeof ( *tls ) );
4640 ref_init ( &tls->refcnt, free_tls );
4641 INIT_LIST_HEAD ( &tls->list );
4646 &tls->refcnt );
4647 tls->client.key = privkey_get ( key ? key : &private_key );
4649 tls->version = TLS_VERSION_MAX;
4654 tls_clear_digest ( tls );
4657 tls->tx.cipherspec.pipe = &tls->channel.tx;
4660 tls->rx.cipherspec.pipe = &tls->channel.rx;
4661 iob_populate ( &tls->rx.iobuf, &tls->rx.header, 0,
4662 sizeof ( tls->rx.header ) );
4663 INIT_LIST_HEAD ( &tls->rx.data );
4664
4665 /* Open secure channel */
4666 if ( ( rc = channel_open ( &tls->channel ) ) != 0 )
4667 goto err_channel;
4668
4669 /* Find or create session */
4670 if ( ( rc = tls_session ( tls, name ) ) != 0 )
4671 goto err_session;
4672 list_add_tail ( &tls->list, &tls->session->conn );
4673
4674 /* Start negotiation */
4675 tls_restart ( tls );
4676
4677 /* Attach to parent interface, mortalise self, and return */
4678 intf_insert ( xfer, &tls->plainstream, &tls->cipherstream );
4679 ref_put ( &tls->refcnt );
4680 return 0;
4681
4682 err_session:
4683 channel_close ( &tls->channel );
4684 err_channel:
4685 ref_put ( &tls->refcnt );
4686 err_alloc:
4687 return rc;
4688}
int channel_open(struct secure_channel *channel)
Open secure channel.
Definition channel.c:1205
static void channel_init(struct secure_channel *channel, struct secure_channel_operations *op)
Initialise secure channel.
Definition channel.h:256
void intf_insert(struct interface *intf, struct interface *upper, struct interface *lower)
Insert a filter interface.
Definition interface.c:402
static void intf_init(struct interface *intf, struct interface_descriptor *desc, struct refcnt *refcnt)
Initialise an object interface.
Definition interface.h:204
static void iob_populate(struct io_buffer *iobuf, void *data, size_t len, size_t max_len)
Create a temporary I/O buffer.
Definition iobuf.h:255
static void process_init_stopped(struct process *process, struct process_descriptor *desc, struct refcnt *refcnt)
Initialise process without adding to process list.
Definition process.h:146
struct x509_root root_certificates
Root certificates.
Definition rootcert.c:79
struct stp_switch root
Root switch.
Definition stp.h:15
A private key.
Definition privkey.h:17
struct refcnt refcnt
Reference counter.
Definition tls.h:480
#define table_start(table)
Get start of linker table.
Definition tables.h:283
static struct interface_descriptor tls_cipherstream_desc
TLS ciphertext stream interface descriptor.
Definition tls.c:4420
static struct secure_channel_operations tls_channel_ops
Secure channel operations.
Definition tls.c:1681
static struct interface_descriptor tls_validator_desc
TLS certificate validator interface descriptor.
Definition tls.c:4507
static struct interface_descriptor tls_plainstream_desc
TLS plaintext stream interface descriptor.
Definition tls.c:4205
static void free_tls(struct refcnt *refcnt)
Free TLS connection.
Definition tls.c:412
static struct process_descriptor tls_process_desc
TLS TX process descriptor.
Definition tls.c:4609

References tls_connection::channel, channel_close(), channel_init(), channel_open(), tls_rx::cipherspec, tls_tx::cipherspec, tls_connection::cipherstream, tls_connection::client, tls_session::conn, tls_rx::data, ENOMEM, free_tls(), tls_connection::group, tls_rx::header, INIT_LIST_HEAD, intf_init(), intf_insert(), iob_populate(), tls_rx::iobuf, key, tls_client::key, tls_connection::legacy_version, tls_connection::list, list_add_tail, malloc(), memset(), name, tls_cipherspec::pipe, tls_connection::plainstream, privkey_get(), tls_tx::process, process_init_stopped(), rc, ref_init, ref_put, tls_connection::refcnt, root, tls_server::root, root_certificates, secure_channel::rx, tls_connection::rx, tls_connection::server, tls_connection::session, tls_cipherspec::suite, tls_connection::suite, table_start, tls_channel_ops, tls_cipher_suite_null, tls_cipherstream_desc, tls_clear_digest(), TLS_LEGACY_VERSION_MAX, TLS_NAMED_GROUPS, tls_plainstream_desc, tls_process_desc, tls_restart(), tls_validator_desc, TLS_VERSION_MAX, secure_channel::tx, tls_connection::tx, tls_server::validator, tls_connection::version, tls_cipherspec::writer, and x509_root_get().

Referenced by apply_syslogs_settings(), https_filter(), ipair_rx_session(), and REQUIRING_SYMBOL().

◆ REQUIRING_SYMBOL()

REQUIRING_SYMBOL ( add_tls )

References add_tls().

◆ REQUIRE_OBJECT()

REQUIRE_OBJECT ( config_crypto )

Variable Documentation

◆ rsa_algorithm

struct pubkey_algorithm rsa_algorithm

Definition at line 199 of file tls.c.

Referenced by __tls_cipher_suite(), __tls_cipher_suite(), __tls_cipher_suite(), __tls_cipher_suite(), __tls_cipher_suite(), __tls_cipher_suite(), __tls_cipher_suite(), __tls_cipher_suite(), __tls_cipher_suite(), __tls_cipher_suite(), __tls_cipher_suite(), __tls_cipher_suite(), __tls_cipher_suite(), __tls_cipher_suite(), __tls_cipher_suite(), __tls_cipher_suite(), __tls_cipher_suite(), __tls_cipher_suite(), icert_cert(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), REQUIRING_SYMBOL(), tls_send_certificate_verify(), and tls_verify_signature().

◆ tls_downgrade_magic

const uint8_t tls_downgrade_magic[7] = TLS_SERVER_DOWNGRADE_MAGIC
static

ServerHello downgrade magic value.

Definition at line 205 of file tls.c.

Referenced by tls_new_server_hello().

◆ tls_hrr_magic

const struct tls_random tls_hrr_magic
static
Initial value:
= {
.bytes = {
0xcf, 0x21, 0xad, 0x74, 0xe5, 0x9a, 0x61, 0x11,
0xbe, 0x1d, 0x8c, 0x02, 0x1e, 0x65, 0xb8, 0x91,
0xc2, 0xa2, 0x11, 0x16, 0x7a, 0xbb, 0x8c, 0x5e,
0x07, 0x9e, 0x09, 0xe2, 0xc8, 0xa8, 0x33, 0x9c
},
}

HelloRetryRequest magic value.

Definition at line 208 of file tls.c.

208 {
209 .bytes = {
210 0xcf, 0x21, 0xad, 0x74, 0xe5, 0x9a, 0x61, 0x11,
211 0xbe, 0x1d, 0x8c, 0x02, 0x1e, 0x65, 0xb8, 0x91,
212 0xc2, 0xa2, 0x11, 0x16, 0x7a, 0xbb, 0x8c, 0x5e,
213 0x07, 0x9e, 0x09, 0xe2, 0xc8, 0xa8, 0x33, 0x9c
214 },
215};

Referenced by tls_new_server_hello().

◆ tls_cipher_suite_null

struct tls_cipher_suite tls_cipher_suite_null
Initial value:
= {
.pubkey = &pubkey_null,
.cipher = &cipher_null,
.digest = &digest_null,
.handshake = &digest_null,
}

Null cipher suite.

Definition at line 618 of file tls.c.

618 {
620 .pubkey = &pubkey_null,
621 .cipher = &cipher_null,
622 .digest = &digest_null,
623 .handshake = &digest_null,
624};

Referenced by add_tls(), tls_change_cipher(), tls_clear_cipher(), tls_new_server_hello(), tls_restart(), and tls_select_cipher().

◆ __tls_anon_named_group

struct tls_named_group tls_pubkey_named_group __tls_anon_named_group
Initial value:
= {
.exchange = &exchange_null,
}
struct exchange_algorithm exchange_null

Null named group.

Public key named group.

Definition at line 1120 of file tls.c.

1120 {
1121 .exchange = &exchange_null,
1122};

◆ tls_null_exchange_algorithm

struct tls_key_exchange_algorithm tls_null_exchange_algorithm
Initial value:
= {
.name = "null",
.group = &tls_null_named_group,
.parse = tls_parse_null,
.map = tls_client_key_exchange_pubkey_map,
}
static int tls_parse_null(struct tls_connection *tls, const struct tls_cursor *cursor, struct tls_key_exchange_parameters *kex __unused)
Parse key exchange parameters from unexpected Server Key Exchange record.
Definition tls.c:1111

Null key exchange algorithm.

Definition at line 1125 of file tls.c.

1125 {
1126 .name = "null",
1127 .group = &tls_null_named_group,
1128 .parse = tls_parse_null,
1129 .map = tls_client_key_exchange_pubkey_map,
1130};

Referenced by __tls_cipher_suite(), __tls_cipher_suite(), and tls_cipher_name().

◆ tls_pubkey_exchange_algorithm

struct tls_key_exchange_algorithm tls_pubkey_exchange_algorithm
Initial value:
= {
.name = "pubkey",
.group = &tls_pubkey_named_group,
.parse = tls_parse_null,
.map = tls_client_key_exchange_pubkey_map,
}

Public key exchange algorithm.

Definition at line 1138 of file tls.c.

1138 {
1139 .name = "pubkey",
1140 .group = &tls_pubkey_named_group,
1141 .parse = tls_parse_null,
1142 .map = tls_client_key_exchange_pubkey_map,
1143};

Referenced by __tls_cipher_suite(), __tls_cipher_suite(), __tls_cipher_suite(), __tls_cipher_suite(), __tls_cipher_suite(), __tls_cipher_suite(), and tls_cipher_name().

◆ tls_dhe_exchange_algorithm

struct tls_key_exchange_algorithm tls_dhe_exchange_algorithm
Initial value:
= {
.name = "dhe",
.group = &tls_null_named_group,
.parse = tls_parse_dhe,
.map = tls_client_key_exchange_dhe_map,
}
static int tls_parse_dhe(struct tls_connection *tls, const struct tls_cursor *cursor, struct tls_key_exchange_parameters *kex)
Parse key exchange parameters from DHE Server Key Exchange record.
Definition tls.c:1153

Ephemeral Diffie-Hellman key exchange algorithm.

Definition at line 1186 of file tls.c.

1186 {
1187 .name = "dhe",
1188 .group = &tls_null_named_group,
1189 .parse = tls_parse_dhe,
1190 .map = tls_client_key_exchange_dhe_map,
1191};

Referenced by __tls_cipher_suite(), __tls_cipher_suite(), __tls_cipher_suite(), __tls_cipher_suite(), __tls_cipher_suite(), and __tls_cipher_suite().

◆ tls_ecdhe_exchange_algorithm

struct tls_key_exchange_algorithm tls_ecdhe_exchange_algorithm
Initial value:
= {
.name = "ecdhe",
.group = &tls_null_named_group,
.parse = tls_parse_ecdhe,
.map = tls_client_key_exchange_ecdhe_map,
}
static int tls_parse_ecdhe(struct tls_connection *tls, const struct tls_cursor *cursor, struct tls_key_exchange_parameters *kex)
Parse key exchange parameters from ECDHE Server Key Exchange record.
Definition tls.c:1202

Ephemeral Elliptic Curve Diffie-Hellman key exchange algorithm.

Definition at line 1241 of file tls.c.

1241 {
1242 .name = "ecdhe",
1243 .group = &tls_null_named_group,
1244 .parse = tls_parse_ecdhe,
1245 .map = tls_client_key_exchange_ecdhe_map,
1246};

Referenced by __tls_cipher_suite(), __tls_cipher_suite(), __tls_cipher_suite(), __tls_cipher_suite(), __tls_cipher_suite(), and __tls_cipher_suite().

◆ tls_channel_ops

struct secure_channel_operations tls_channel_ops
static
Initial value:
= {
.verify = tls_channel_verify,
}
static int tls_channel_save(struct secure_channel *channel, struct secure_preshared_identity *psid)
Save a pre-shared key for future resumption of the key schedule.
Definition tls.c:1586
static int tls_channel_load(struct secure_channel *channel, struct secure_preshared_identity *psid)
Load a pre-shared key and resume the key schedule.
Definition tls.c:1623
static void tls_channel_reset(struct secure_channel *channel)
Reset the key schedule.
Definition tls.c:1524
static int tls_channel_verify(struct secure_channel *channel, const void *auth, size_t len)
Verify authenticator value.
Definition tls.c:1650
static int tls_channel_apply(struct secure_channel *channel, struct exchange_algorithm *exchange, const void *shared, int *accumulated)
Apply a new shared secret to key schedule.
Definition tls.c:1541

Secure channel operations.

Definition at line 1681 of file tls.c.

1681 {
1682 .reset = tls_channel_reset,
1683 .apply = tls_channel_apply,
1684 .save = tls_channel_save,
1685 .load = tls_channel_load,
1686 .verify = tls_channel_verify,
1687};

Referenced by add_tls().

◆ tls_plainstream_ops

struct interface_operation tls_plainstream_ops[]
static
Initial value:
= {
}
void intf_close(struct interface *intf, int rc)
Close an object interface.
Definition interface.c:250
#define INTF_OP(op_type, object_type, op_func)
Define an object interface operation.
Definition interface.h:33
Job progress.
Definition job.h:16
static int tls_progress(struct tls_connection *tls, struct job_progress *progress)
Report job progress.
Definition tls.c:4182
static int tls_plainstream_deliver(struct tls_connection *tls, struct io_buffer *iobuf, struct xfer_metadata *meta __unused)
Deliver datagram as raw data.
Definition tls.c:4154
static size_t tls_plainstream_window(struct tls_connection *tls)
Check flow control window.
Definition tls.c:4137
int xfer_deliver(struct interface *intf, struct io_buffer *iobuf, struct xfer_metadata *meta)
Deliver datagram.
Definition xfer.c:195

TLS plaintext stream interface operations.

Definition at line 4194 of file tls.c.

◆ tls_plainstream_desc

struct interface_descriptor tls_plainstream_desc
static
Initial value:
=
INTF_DESC_PASSTHRU ( struct tls_connection, plainstream,
tls_plainstream_ops, cipherstream )
#define INTF_DESC_PASSTHRU(object_type, intf, operations, passthru)
Define an object interface descriptor with pass-through interface.
Definition interface.h:98
static struct interface_operation tls_plainstream_ops[]
TLS plaintext stream interface operations.
Definition tls.c:4194

TLS plaintext stream interface descriptor.

Definition at line 4205 of file tls.c.

Referenced by add_tls().

◆ tls_cipherstream_ops

struct interface_operation tls_cipherstream_ops[]
static
Initial value:
= {
}
static int tls_cipherstream_deliver(struct tls_connection *tls, struct io_buffer *iobuf, struct xfer_metadata *xfer __unused)
Receive new ciphertext.
Definition tls.c:4358
static size_t tls_cipherstream_window(struct tls_connection *tls)
Check flow control window.
Definition tls.c:4341

TLS ciphertext stream interface operations.

Definition at line 4409 of file tls.c.

◆ tls_cipherstream_desc

struct interface_descriptor tls_cipherstream_desc
static
Initial value:
=
INTF_DESC_PASSTHRU ( struct tls_connection, cipherstream,
tls_cipherstream_ops, plainstream )
static struct interface_operation tls_cipherstream_ops[]
TLS ciphertext stream interface operations.
Definition tls.c:4409

TLS ciphertext stream interface descriptor.

Definition at line 4420 of file tls.c.

Referenced by add_tls().

◆ tls_validator_ops

struct interface_operation tls_validator_ops[]
static
Initial value:
= {
}
static void tls_validator_done(struct tls_connection *tls, int rc)
Handle certificate validation completion.
Definition tls.c:4465

TLS certificate validator interface operations.

Definition at line 4502 of file tls.c.

4502 {
4504};

◆ tls_validator_desc

struct interface_descriptor tls_validator_desc
static
Initial value:
=
INTF_DESC ( struct tls_connection, server.validator,
#define INTF_DESC(object_type, intf, operations)
Define an object interface descriptor.
Definition interface.h:81
static struct interface_operation tls_validator_ops[]
TLS certificate validator interface operations.
Definition tls.c:4502

TLS certificate validator interface descriptor.

Definition at line 4507 of file tls.c.

Referenced by add_tls().

◆ tls_process_desc

struct process_descriptor tls_process_desc
static
Initial value:
=
#define PROC_DESC_ONCE(object_type, process, _step)
Define a process descriptor for a process that runs only once.
Definition process.h:98
static void tls_tx_step(struct tls_connection *tls)
TLS TX state machine.
Definition tls.c:4523
u8 tx[WPA_TKIP_MIC_KEY_LEN]
MIC key for packets to the AP.
Definition wpa.h:4

TLS TX process descriptor.

Definition at line 4609 of file tls.c.

Referenced by add_tls().