iPXE
tls.c File Reference

Transport Layer Security Protocol. More...

#include <stdint.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>
#include <byteswap.h>
#include <ipxe/pending.h>
#include <ipxe/hmac.h>
#include <ipxe/md5.h>
#include <ipxe/sha1.h>
#include <ipxe/sha256.h>
#include <ipxe/md5_sha1.h>
#include <ipxe/aes.h>
#include <ipxe/rsa.h>
#include <ipxe/hkdf.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/rbg.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.

Data Structures

struct  tls24_t
 A TLS 24-bit integer. More...

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_HELLO   __einfo_error ( EINFO_EINVAL_HELLO )
#define EINFO_EINVAL_HELLO
#define EINVAL_CERTIFICATE   __einfo_error ( EINFO_EINVAL_CERTIFICATE )
#define EINFO_EINVAL_CERTIFICATE
#define EINVAL_CERTIFICATES   __einfo_error ( EINFO_EINVAL_CERTIFICATES )
#define EINFO_EINVAL_CERTIFICATES
#define EINVAL_HELLO_DONE   __einfo_error ( EINFO_EINVAL_HELLO_DONE )
#define EINFO_EINVAL_HELLO_DONE
#define EINVAL_FINISHED   __einfo_error ( EINFO_EINVAL_FINISHED )
#define EINFO_EINVAL_FINISHED
#define EINVAL_HANDSHAKE   __einfo_error ( EINFO_EINVAL_HANDSHAKE )
#define EINFO_EINVAL_HANDSHAKE
#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_TICKET   __einfo_error ( EINFO_EINVAL_TICKET )
#define EINFO_EINVAL_TICKET
#define EINVAL_KEY_EXCHANGE   __einfo_error ( EINFO_EINVAL_KEY_EXCHANGE )
#define EINFO_EINVAL_KEY_EXCHANGE
#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 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_EMS   __einfo_error ( EINFO_EPERM_EMS )
#define EINFO_EPERM_EMS
#define EPERM_BOUND   __einfo_error ( EINFO_EPERM_BOUND )
#define EINFO_EPERM_BOUND
#define EPROTO_VERSION   __einfo_error ( EINFO_EPROTO_VERSION )
#define EINFO_EPROTO_VERSION
#define tls_prf_label(tls, out, out_len, label, ...)
 Generate secure pseudo-random data.
#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_regenerate_ephemeral_master (struct tls_connection *tls)
 Regenerate ephemeral master secret.
static void tls_tx_resume_all (struct tls_session *session)
 Resume TX state machine for all connections within a session.
static struct io_buffertls_alloc_iob (struct tls_connection *tls, size_t len)
 Allocate I/O buffer for transmitted record(s).
static int tls_send_handshake (struct tls_connection *tls, const void *data, size_t len)
 Transmit Handshake record.
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_cipher (struct tls_connection *tls, struct tls_cipherspec *cipherspec)
static void tls_clear_digest (struct tls_connection *tls)
 Clear key schedule digest algorithm.
static void tls_verify_handshake (struct tls_connection *tls, void *out)
 Calculate handshake verification hash.
static unsigned long tls_uint24 (const tls24_t *field24)
 Extract 24-bit field value.
static void tls_set_uint24 (tls24_t *field24, unsigned long value)
 Set 24-bit field value.
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 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 int tls_generate_ephemeral_master (struct tls_connection *tls)
 Generate ephemeral master secret.
static void tls_ephemeral (struct tls_connection *tls, const void *info, size_t info_len, void *out, size_t len)
 Generate ephemeral secret.
static void tls_ephemeral_label (struct tls_connection *tls, const char *label, void *out, size_t len)
 Generate ephemeral secret from label.
static void tls_clear_binding (struct tls_connection *tls)
 Clear key schedule binding.
static void tls_set_binding (struct tls_connection *tls, struct x509_certificate *cert)
 Bind key schedule to a server identity.
static int tls_set_digest (struct tls_connection *tls, struct digest_algorithm *digest)
 Set key schedule digest algorithm.
static void tls_hmac_update_va (struct digest_algorithm *digest, void *ctx, va_list args)
 Update HMAC with a list of ( data, len ) pairs.
static void tls_p_hash_va (struct tls_connection *tls, struct digest_algorithm *digest, const void *hkey, void *out, size_t out_len, va_list seeds)
 Generate secure pseudo-random data using a single hash function.
static void tls_prf (struct tls_connection *tls, void *out, size_t out_len,...)
 Generate secure pseudo-random data.
static void tls_set_kdf_master (struct tls_connection *tls, const void *secret, size_t secret_len)
 Set key derivation function master secret.
static int tls_share_ephemeral (struct tls_connection *tls, void *public)
 Share ephemeral public key.
static int tls_agree_ephemeral (struct tls_connection *tls, const void *partner, size_t partner_len, int strip)
 Agree ephemeral public key (i.e.
static void tls_generate_master_secret (struct tls_connection *tls)
 Generate master secret.
static int tls_generate_keys (struct tls_connection *tls)
 Generate key material.
static void tls_generate_resumption_master (struct tls_connection *tls)
 Generate resumption master secret.
static void tls_resume_secret (struct tls_connection *tls)
 Resume from resumption master secret.
static int tls_add_handshake (struct tls_connection *tls, const void *data, size_t len)
 Add handshake record to verification hash.
static struct tls_cipher_suitetls_find_cipher_suite (unsigned int cipher_suite)
 Identify cipher suite.
static void tls_clear_cipher (struct tls_connection *tls __unused, struct tls_cipherspec *cipherspec)
 Clear cipher suite.
static int tls_set_cipher (struct tls_connection *tls, struct tls_cipherspec *cipherspec, struct tls_cipher_suite *suite)
 Set cipher suite.
static int tls_select_cipher (struct tls_connection *tls, unsigned int cipher_suite)
 Select next cipher suite.
static int tls_change_cipher (struct tls_connection *tls, struct tls_cipherspec_pair *pair)
 Activate next cipher suite.
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_algorithmtls_find_signature_hash (unsigned int code)
 Find TLS signature and hash algorithm.
static struct tls_named_grouptls_find_named_group (unsigned int named_group)
 Identify named key exchange group.
static struct tls_named_grouptls_find_param_group (const void *dh_p, size_t dh_p_len, const void *dh_g, size_t dh_g_len)
 Identify named key exchange group by Diffie-Hellman parameters.
static int tls_verify_dh_params (struct tls_connection *tls, const void *data, size_t len, size_t param_len)
 Verify Diffie-Hellman parameter signature.
static int tls_new_server_key_exchange_pubkey (struct tls_connection *tls, const void *data, size_t len)
 Receive new Server Key Exchange record using public key transport.
static int tls_send_client_key_exchange_pubkey (struct tls_connection *tls)
 Transmit Client Key Exchange record using public key exchange.
static int tls_new_server_key_exchange_dhe (struct tls_connection *tls, const void *data, size_t len)
 Receive new Server Key Exchange record using DHE key exchange.
static int tls_send_client_key_exchange_dhe (struct tls_connection *tls)
 Transmit Client Key Exchange record using DHE key exchange.
static int tls_new_server_key_exchange_ecdhe (struct tls_connection *tls, const void *data, size_t len)
 Receive new Server Key Exchange record using ECDHE key exchange.
static int tls_send_client_key_exchange_ecdhe (struct tls_connection *tls)
 Transmit Client Key Exchange record using ECDHE key exchange.
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_client_hello (struct tls_connection *tls, int(*action)(struct tls_connection *tls, const void *data, size_t len))
 Digest or transmit Client Hello 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 void *data __unused, size_t len __unused)
 Receive new Hello Request handshake record.
static int tls_new_server_hello (struct tls_connection *tls, const void *data, size_t len)
 Receive new Server Hello handshake record.
static int tls_new_session_ticket (struct tls_connection *tls, const void *data, size_t len)
 Receive New Session Ticket handshake record.
static int tls_parse_chain (struct tls_connection *tls, const void *data, size_t len)
 Parse certificate chain.
static int tls_new_certificate (struct tls_connection *tls, const void *data, size_t len)
 Receive new Certificate handshake record.
static int tls_new_server_key_exchange (struct tls_connection *tls, const void *data, size_t len)
 Receive new Server Key Exchange handshake record.
static int tls_new_certificate_request (struct tls_connection *tls, const void *data __unused, size_t len __unused)
 Receive new Certificate Request handshake record.
static int tls_new_server_hello_done (struct tls_connection *tls, const void *data, size_t len)
 Receive new Server Hello Done handshake record.
static int tls_new_finished (struct tls_connection *tls, const void *data, size_t len)
 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_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.
static int tls_session (struct tls_connection *tls, const char *name)
 Find or create session for TLS connection.
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 tls_cipher_suite tls_cipher_suite_null
 Null cipher suite.
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 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 59 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:181
#define EINFO_EINVAL
Definition errno.h:430

Definition at line 60 of file tls.c.

60#define EINFO_EINVAL_CHANGE_CIPHER \
61 __einfo_uniqify ( EINFO_EINVAL, 0x01, \
62 "Invalid Change Cipher record" )

◆ EINVAL_ALERT

#define EINVAL_ALERT   __einfo_error ( EINFO_EINVAL_ALERT )

Definition at line 63 of file tls.c.

Referenced by tls_new_alert().

◆ EINFO_EINVAL_ALERT

#define EINFO_EINVAL_ALERT
Value:
"Invalid Alert record" )

Definition at line 64 of file tls.c.

64#define EINFO_EINVAL_ALERT \
65 __einfo_uniqify ( EINFO_EINVAL, 0x02, \
66 "Invalid Alert record" )

◆ EINVAL_HELLO

#define EINVAL_HELLO   __einfo_error ( EINFO_EINVAL_HELLO )

Definition at line 67 of file tls.c.

Referenced by tls_new_server_hello().

◆ EINFO_EINVAL_HELLO

#define EINFO_EINVAL_HELLO
Value:
"Invalid Server Hello record" )

Definition at line 68 of file tls.c.

68#define EINFO_EINVAL_HELLO \
69 __einfo_uniqify ( EINFO_EINVAL, 0x03, \
70 "Invalid Server Hello record" )

◆ EINVAL_CERTIFICATE

#define EINVAL_CERTIFICATE   __einfo_error ( EINFO_EINVAL_CERTIFICATE )

Definition at line 71 of file tls.c.

Referenced by tls_parse_chain().

◆ EINFO_EINVAL_CERTIFICATE

#define EINFO_EINVAL_CERTIFICATE
Value:
"Invalid Certificate" )

Definition at line 72 of file tls.c.

72#define EINFO_EINVAL_CERTIFICATE \
73 __einfo_uniqify ( EINFO_EINVAL, 0x04, \
74 "Invalid Certificate" )

◆ EINVAL_CERTIFICATES

#define EINVAL_CERTIFICATES   __einfo_error ( EINFO_EINVAL_CERTIFICATES )

Definition at line 75 of file tls.c.

Referenced by tls_new_certificate().

◆ EINFO_EINVAL_CERTIFICATES

#define EINFO_EINVAL_CERTIFICATES
Value:
"Invalid Server Certificate record" )

Definition at line 76 of file tls.c.

76#define EINFO_EINVAL_CERTIFICATES \
77 __einfo_uniqify ( EINFO_EINVAL, 0x05, \
78 "Invalid Server Certificate record" )

◆ EINVAL_HELLO_DONE

#define EINVAL_HELLO_DONE   __einfo_error ( EINFO_EINVAL_HELLO_DONE )

Definition at line 79 of file tls.c.

Referenced by tls_new_server_hello_done().

◆ EINFO_EINVAL_HELLO_DONE

#define EINFO_EINVAL_HELLO_DONE
Value:
"Invalid Server Hello Done record" )

Definition at line 80 of file tls.c.

80#define EINFO_EINVAL_HELLO_DONE \
81 __einfo_uniqify ( EINFO_EINVAL, 0x06, \
82 "Invalid Server Hello Done record" )

◆ EINVAL_FINISHED

#define EINVAL_FINISHED   __einfo_error ( EINFO_EINVAL_FINISHED )

Definition at line 83 of file tls.c.

Referenced by tls_new_finished().

◆ EINFO_EINVAL_FINISHED

#define EINFO_EINVAL_FINISHED
Value:
"Invalid Server Finished record" )

Definition at line 84 of file tls.c.

84#define EINFO_EINVAL_FINISHED \
85 __einfo_uniqify ( EINFO_EINVAL, 0x07, \
86 "Invalid Server Finished record" )

◆ EINVAL_HANDSHAKE

#define EINVAL_HANDSHAKE   __einfo_error ( EINFO_EINVAL_HANDSHAKE )

Definition at line 87 of file tls.c.

◆ EINFO_EINVAL_HANDSHAKE

#define EINFO_EINVAL_HANDSHAKE
Value:
"Invalid Handshake record" )

Definition at line 88 of file tls.c.

88#define EINFO_EINVAL_HANDSHAKE \
89 __einfo_uniqify ( EINFO_EINVAL, 0x08, \
90 "Invalid Handshake record" )

◆ EINVAL_IV

#define EINVAL_IV   __einfo_error ( EINFO_EINVAL_IV )

Definition at line 91 of file tls.c.

Referenced by tls_new_ciphertext().

◆ EINFO_EINVAL_IV

#define EINFO_EINVAL_IV
Value:
"Invalid initialisation vector" )

Definition at line 92 of file tls.c.

92#define EINFO_EINVAL_IV \
93 __einfo_uniqify ( EINFO_EINVAL, 0x0a, \
94 "Invalid initialisation vector" )

◆ EINVAL_PADDING

#define EINVAL_PADDING   __einfo_error ( EINFO_EINVAL_PADDING )

Definition at line 95 of file tls.c.

Referenced by tls_verify_padding().

◆ EINFO_EINVAL_PADDING

#define EINFO_EINVAL_PADDING
Value:
"Invalid block padding" )

Definition at line 96 of file tls.c.

96#define EINFO_EINVAL_PADDING \
97 __einfo_uniqify ( EINFO_EINVAL, 0x0b, \
98 "Invalid block padding" )

◆ EINVAL_RX_STATE

#define EINVAL_RX_STATE   __einfo_error ( EINFO_EINVAL_RX_STATE )

Definition at line 99 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 100 of file tls.c.

100#define EINFO_EINVAL_RX_STATE \
101 __einfo_uniqify ( EINFO_EINVAL, 0x0c, \
102 "Invalid receive state" )

◆ EINVAL_MAC

#define EINVAL_MAC   __einfo_error ( EINFO_EINVAL_MAC )

Definition at line 103 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 104 of file tls.c.

104#define EINFO_EINVAL_MAC \
105 __einfo_uniqify ( EINFO_EINVAL, 0x0d, \
106 "Invalid MAC or authentication tag" )

◆ EINVAL_TICKET

#define EINVAL_TICKET   __einfo_error ( EINFO_EINVAL_TICKET )

Definition at line 107 of file tls.c.

Referenced by tls_new_session_ticket().

◆ EINFO_EINVAL_TICKET

#define EINFO_EINVAL_TICKET
Value:
"Invalid New Session Ticket record")

Definition at line 108 of file tls.c.

108#define EINFO_EINVAL_TICKET \
109 __einfo_uniqify ( EINFO_EINVAL, 0x0e, \
110 "Invalid New Session Ticket record")

◆ EINVAL_KEY_EXCHANGE

◆ EINFO_EINVAL_KEY_EXCHANGE

#define EINFO_EINVAL_KEY_EXCHANGE
Value:
"Invalid Server Key Exchange record" )

Definition at line 112 of file tls.c.

112#define EINFO_EINVAL_KEY_EXCHANGE \
113 __einfo_uniqify ( EINFO_EINVAL, 0x0f, \
114 "Invalid Server Key Exchange record" )

◆ EIO_ALERT

#define EIO_ALERT   __einfo_error ( EINFO_EIO_ALERT )

Definition at line 115 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:435

Definition at line 116 of file tls.c.

116#define EINFO_EIO_ALERT \
117 __einfo_uniqify ( EINFO_EIO, 0x01, \
118 "Unknown alert level" )

◆ ENOENT_CERT

#define ENOENT_CERT   __einfo_error ( EINFO_ENOENT_CERT )

◆ EINFO_ENOENT_CERT

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

Definition at line 120 of file tls.c.

120#define EINFO_ENOENT_CERT \
121 __einfo_uniqify ( EINFO_ENOENT, 0x01, \
122 "Missing server certificate" )

◆ ENOMEM_CONTEXT

#define ENOMEM_CONTEXT   __einfo_error ( EINFO_ENOMEM_CONTEXT )

Definition at line 123 of file tls.c.

Referenced by tls_set_cipher().

◆ EINFO_ENOMEM_CONTEXT

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

Definition at line 124 of file tls.c.

124#define EINFO_ENOMEM_CONTEXT \
125 __einfo_uniqify ( EINFO_ENOMEM, 0x01, \
126 "Not enough space for crypto context" )

◆ ENOMEM_CERTIFICATE

#define ENOMEM_CERTIFICATE   __einfo_error ( EINFO_ENOMEM_CERTIFICATE )

Definition at line 127 of file tls.c.

Referenced by tls_send_certificate().

◆ EINFO_ENOMEM_CERTIFICATE

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

Definition at line 128 of file tls.c.

128#define EINFO_ENOMEM_CERTIFICATE \
129 __einfo_uniqify ( EINFO_ENOMEM, 0x02, \
130 "Not enough space for certificate" )

◆ ENOMEM_CHAIN

#define ENOMEM_CHAIN   __einfo_error ( EINFO_ENOMEM_CHAIN )

Definition at line 131 of file tls.c.

Referenced by tls_parse_chain().

◆ EINFO_ENOMEM_CHAIN

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

Definition at line 132 of file tls.c.

132#define EINFO_ENOMEM_CHAIN \
133 __einfo_uniqify ( EINFO_ENOMEM, 0x03, \
134 "Not enough space for certificate chain" )

◆ ENOMEM_TX_PLAINTEXT

#define ENOMEM_TX_PLAINTEXT   __einfo_error ( EINFO_ENOMEM_TX_PLAINTEXT )

Definition at line 135 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 136 of file tls.c.

136#define EINFO_ENOMEM_TX_PLAINTEXT \
137 __einfo_uniqify ( EINFO_ENOMEM, 0x04, \
138 "Not enough space for transmitted plaintext" )

◆ ENOMEM_TX_CIPHERTEXT

#define ENOMEM_TX_CIPHERTEXT   __einfo_error ( EINFO_ENOMEM_TX_CIPHERTEXT )

Definition at line 139 of file tls.c.

◆ EINFO_ENOMEM_TX_CIPHERTEXT

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

Definition at line 140 of file tls.c.

140#define EINFO_ENOMEM_TX_CIPHERTEXT \
141 __einfo_uniqify ( EINFO_ENOMEM, 0x05, \
142 "Not enough space for transmitted ciphertext" )

◆ ENOMEM_RX_DATA

#define ENOMEM_RX_DATA   __einfo_error ( EINFO_ENOMEM_RX_DATA )

Definition at line 143 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 144 of file tls.c.

144#define EINFO_ENOMEM_RX_DATA \
145 __einfo_uniqify ( EINFO_ENOMEM, 0x07, \
146 "Not enough space for received data" )

◆ ENOMEM_RX_CONCAT

#define ENOMEM_RX_CONCAT   __einfo_error ( EINFO_ENOMEM_RX_CONCAT )

Definition at line 147 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 148 of file tls.c.

148#define EINFO_ENOMEM_RX_CONCAT \
149 __einfo_uniqify ( EINFO_ENOMEM, 0x08, \
150 "Not enough space to concatenate received data" )

◆ ENOTSUP_CIPHER

#define ENOTSUP_CIPHER   __einfo_error ( EINFO_ENOTSUP_CIPHER )

Definition at line 151 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:591

Definition at line 152 of file tls.c.

152#define EINFO_ENOTSUP_CIPHER \
153 __einfo_uniqify ( EINFO_ENOTSUP, 0x01, \
154 "Unsupported cipher" )

◆ ENOTSUP_NULL

#define ENOTSUP_NULL   __einfo_error ( EINFO_ENOTSUP_NULL )

Definition at line 155 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 156 of file tls.c.

156#define EINFO_ENOTSUP_NULL \
157 __einfo_uniqify ( EINFO_ENOTSUP, 0x02, \
158 "Refusing to use null cipher" )

◆ ENOTSUP_SIG_HASH

#define ENOTSUP_SIG_HASH   __einfo_error ( EINFO_ENOTSUP_SIG_HASH )

Definition at line 159 of file tls.c.

Referenced by tls_send_certificate_verify(), and tls_verify_dh_params().

◆ EINFO_ENOTSUP_SIG_HASH

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

Definition at line 160 of file tls.c.

160#define EINFO_ENOTSUP_SIG_HASH \
161 __einfo_uniqify ( EINFO_ENOTSUP, 0x03, \
162 "Unsupported signature and hash algorithm" )

◆ ENOTSUP_VERSION

#define ENOTSUP_VERSION   __einfo_error ( EINFO_ENOTSUP_VERSION )

Definition at line 163 of file tls.c.

◆ EINFO_ENOTSUP_VERSION

#define EINFO_ENOTSUP_VERSION
Value:
"Unsupported protocol version" )

Definition at line 164 of file tls.c.

164#define EINFO_ENOTSUP_VERSION \
165 __einfo_uniqify ( EINFO_ENOTSUP, 0x04, \
166 "Unsupported protocol version" )

◆ ENOTSUP_GROUP

#define ENOTSUP_GROUP   __einfo_error ( EINFO_ENOTSUP_GROUP )

Definition at line 167 of file tls.c.

Referenced by tls_new_server_key_exchange_dhe(), and tls_new_server_key_exchange_ecdhe().

◆ EINFO_ENOTSUP_GROUP

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

Definition at line 168 of file tls.c.

168#define EINFO_ENOTSUP_GROUP \
169 __einfo_uniqify ( EINFO_ENOTSUP, 0x05, \
170 "Unsupported key exchange group" )

◆ EPERM_ALERT

#define EPERM_ALERT   __einfo_error ( EINFO_EPERM_ALERT )

Definition at line 171 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:616

Definition at line 172 of file tls.c.

172#define EINFO_EPERM_ALERT \
173 __einfo_uniqify ( EINFO_EPERM, 0x01, \
174 "Received fatal alert" )

◆ EPERM_VERIFY

#define EPERM_VERIFY   __einfo_error ( EINFO_EPERM_VERIFY )

Definition at line 175 of file tls.c.

Referenced by tls_new_finished().

◆ EINFO_EPERM_VERIFY

#define EINFO_EPERM_VERIFY
Value:
"Handshake verification failed" )

Definition at line 176 of file tls.c.

176#define EINFO_EPERM_VERIFY \
177 __einfo_uniqify ( EINFO_EPERM, 0x02, \
178 "Handshake verification failed" )

◆ EPERM_RENEG_INSECURE

#define EPERM_RENEG_INSECURE   __einfo_error ( EINFO_EPERM_RENEG_INSECURE )

Definition at line 179 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 180 of file tls.c.

180#define EINFO_EPERM_RENEG_INSECURE \
181 __einfo_uniqify ( EINFO_EPERM, 0x04, \
182 "Secure renegotiation not supported" )

◆ EPERM_RENEG_VERIFY

#define EPERM_RENEG_VERIFY   __einfo_error ( EINFO_EPERM_RENEG_VERIFY )

Definition at line 183 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 184 of file tls.c.

184#define EINFO_EPERM_RENEG_VERIFY \
185 __einfo_uniqify ( EINFO_EPERM, 0x05, \
186 "Secure renegotiation verification failed" )

◆ EPERM_KEY_EXCHANGE

#define EPERM_KEY_EXCHANGE   __einfo_error ( EINFO_EPERM_KEY_EXCHANGE )

Definition at line 187 of file tls.c.

Referenced by tls_verify_dh_params().

◆ EINFO_EPERM_KEY_EXCHANGE

#define EINFO_EPERM_KEY_EXCHANGE
Value:
"ServerKeyExchange verification failed" )

Definition at line 188 of file tls.c.

188#define EINFO_EPERM_KEY_EXCHANGE \
189 __einfo_uniqify ( EINFO_EPERM, 0x06, \
190 "ServerKeyExchange verification failed" )

◆ EPERM_EMS

#define EPERM_EMS   __einfo_error ( EINFO_EPERM_EMS )

Definition at line 191 of file tls.c.

Referenced by tls_new_server_hello().

◆ EINFO_EPERM_EMS

#define EINFO_EPERM_EMS
Value:
"Extended master secret extension mismatch" )

Definition at line 192 of file tls.c.

192#define EINFO_EPERM_EMS \
193 __einfo_uniqify ( EINFO_EPERM, 0x07, \
194 "Extended master secret extension mismatch" )

◆ EPERM_BOUND

#define EPERM_BOUND   __einfo_error ( EINFO_EPERM_BOUND )

Definition at line 195 of file tls.c.

Referenced by tls_send_finished().

◆ EINFO_EPERM_BOUND

#define EINFO_EPERM_BOUND
Value:
"Bound identity not validated" )

Definition at line 196 of file tls.c.

196#define EINFO_EPERM_BOUND \
197 __einfo_uniqify ( EINFO_EPERM, 0x08, \
198 "Bound identity not validated" )

◆ EPROTO_VERSION

#define EPROTO_VERSION   __einfo_error ( EINFO_EPROTO_VERSION )

Definition at line 199 of file tls.c.

Referenced by tls_new_server_hello().

◆ EINFO_EPROTO_VERSION

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

Definition at line 200 of file tls.c.

200#define EINFO_EPROTO_VERSION \
201 __einfo_uniqify ( EINFO_EPROTO, 0x01, \
202 "Illegal protocol version upgrade" )

◆ tls_prf_label

#define tls_prf_label ( tls,
out,
out_len,
label,
... )
Value:
tls_prf ( (tls), (out), (out_len), \
label, ( sizeof ( label ) - 1 ), __VA_ARGS__, NULL )
#define NULL
NULL pointer (VOID *).
Definition Base.h:321
__be32 out[4]
Definition CIB_PRM.h:8
A text label widget.
Definition label.h:16
static void tls_prf(struct tls_connection *tls, void *out, size_t out_len,...)
Generate secure pseudo-random data.
Definition tls.c:693

Generate secure pseudo-random data.

Parameters
tlsTLS connection
outOutput buffer
out_lenLength of output buffer
labelString literal label
...( data, len ) pairs of seed data

Definition at line 746 of file tls.c.

746#define tls_prf_label( tls, out, out_len, label, ... ) \
747 tls_prf ( (tls), (out), (out_len), \
748 label, ( sizeof ( label ) - 1 ), __VA_ARGS__, NULL )

Referenced by tls_generate_keys(), tls_generate_master_secret(), tls_new_finished(), and tls_send_finished().

◆ TLS_NUM_CIPHER_SUITES

#define TLS_NUM_CIPHER_SUITES   table_num_entries ( TLS_CIPHER_SUITES )

Number of supported cipher suites.

Definition at line 1199 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 1345 of file tls.c.

1345#define TLS_NUM_SIG_HASH_ALGORITHMS \
1346 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.

References data, len, and type.

◆ tls_regenerate_ephemeral_master()

void tls_regenerate_ephemeral_master ( struct tls_connection * tls)
static

Regenerate ephemeral master secret.

Parameters
tlsTLS connection

Definition at line 488 of file tls.c.

488 {
489 struct tls_key_schedule *key = &tls->key;
490
491 /* Derive a new ephemeral master secret */
492 tls_ephemeral_label ( tls, "key reset", key->ephemeral,
493 sizeof ( key->ephemeral ) );
494
495 /* (Re)generate client random bytes */
496 tls_ephemeral_label ( tls, "client random", &tls->client.random.random,
497 sizeof ( tls->client.random.random ) );
498}
union @162305117151260234136356364136041353210355154177 key
uint8_t random[32]
Random data.
Definition tls.h:328
struct tls_client_random random
Random bytes.
Definition tls.h:499
struct tls_key_schedule key
Key schedule.
Definition tls.h:557
struct tls_client client
Client state.
Definition tls.h:563
TLS key schedule.
Definition tls.h:370
static void tls_ephemeral_label(struct tls_connection *tls, const char *label, void *out, size_t len)
Generate ephemeral secret from label.
Definition tls.c:474

References tls_connection::client, key, tls_connection::key, tls_client::random, tls_client_random::random, and tls_ephemeral_label().

Referenced by tls_close(), and tls_restart().

◆ 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 1925 of file tls.c.

1925 {
1926 struct tls_connection *tls;
1927
1929 tls_tx_resume ( tls );
1930}
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition list.h:432
A TLS connection.
Definition tls.h:525
struct tls_session * session
Session.
Definition tls.h:530
struct list_head list
List of connections within the same session.
Definition tls.h:532
struct list_head conn
List of connections.
Definition tls.h:363
static void tls_tx_resume(struct tls_connection *tls)
Resume TX state machine.
Definition tls.c:1916

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

Referenced by tls_close(), and tls_new_finished().

◆ 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 3472 of file tls.c.

3473 {
3474 struct io_buffer *iobuf;
3475 size_t reserve;
3476
3477 /* Calculate maximum additional length to reserve */
3478 reserve = tls_iob_reserved ( tls, len );
3479
3480 /* Allocate I/O buffer */
3481 iobuf = xfer_alloc_iob ( &tls->cipherstream, ( reserve + len ) );
3482 if ( ! iobuf )
3483 return NULL;
3484
3485 /* Reserve space */
3486 iob_reserve ( iobuf, reserve );
3487
3488 return iobuf;
3489}
ring len
Length.
Definition dwmac.h:226
#define iob_reserve(iobuf, len)
Definition iobuf.h:72
A persistent I/O buffer.
Definition iobuf.h:38
struct interface cipherstream
Ciphertext stream.
Definition tls.h:545
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:3445
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_send_certificate(), and tls_send_plaintext().

◆ tls_send_handshake()

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

Transmit Handshake record.

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

Definition at line 1963 of file tls.c.

1964 {
1965
1966 /* Send record */
1968}
uint8_t data[48]
Additional event data.
Definition ena.h:11
static int tls_send_plaintext(struct tls_connection *tls, unsigned int type, const void *data, size_t len)
Send plaintext record.
Definition tls.c:3646
#define TLS_TYPE_HANDSHAKE
Handshake content type.
Definition tls.h:61

References data, len, tls_send_plaintext(), and TLS_TYPE_HANDSHAKE.

Referenced by tls_send_certificate_verify(), tls_send_client_hello(), tls_send_client_key_exchange_dhe(), tls_send_client_key_exchange_ecdhe(), tls_send_client_key_exchange_pubkey(), and tls_send_finished().

◆ 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 2406 of file tls.c.

2407 {
2408 const struct {
2409 uint8_t level;
2410 uint8_t description;
2411 } __attribute__ (( packed )) alert = {
2412 .level = level,
2413 .description = description,
2414 };
2415
2416 /* Send record */
2417 return tls_send_plaintext ( tls, TLS_TYPE_ALERT, &alert,
2418 sizeof ( alert ) );
2419}
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
#define TLS_TYPE_ALERT
Alert content type.
Definition tls.h:58

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 3499 of file tls.c.

3500 {
3501 struct tls_cipherspec *cipherspec = &tls->tx.cipherspec.active;
3502 struct tls_cipher_suite *suite = cipherspec->suite;
3503 struct cipher_algorithm *cipher = suite->cipher;
3504 struct digest_algorithm *digest = suite->digest;
3505 struct {
3506 uint8_t fixed[suite->fixed_iv_len];
3507 uint8_t rec[suite->record_iv_len];
3508 } __attribute__ (( packed )) iv;
3509 struct tls_auth_header authhdr;
3510 struct tls_header *tlshdr;
3511 uint8_t mac[digest->digestsize];
3512 const void *plaintext;
3513 const void *encrypt;
3514 void *ciphertext;
3515 size_t record_len;
3516 size_t encrypt_len;
3517 size_t pad_len;
3518 size_t len;
3519 int rc;
3520
3521 /* Record plaintext pointer and length */
3522 plaintext = iobuf->data;
3523 len = iob_len ( iobuf );
3524
3525 /* Add to handshake digest if applicable */
3526 if ( type == TLS_TYPE_HANDSHAKE )
3527 tls_add_handshake ( tls, plaintext, len );
3528
3529 /* Start constructing ciphertext at start of reserved space */
3530 iob_push ( iobuf, tls_iob_reserved ( tls, len ) );
3531 iob_unput ( iobuf, iob_len ( iobuf ) );
3532
3533 /* Construct records */
3534 do {
3535 /* Limit length of this record (may be zero) */
3536 record_len = len;
3537 if ( record_len > TLS_TX_BUFSIZE )
3538 record_len = TLS_TX_BUFSIZE;
3539
3540 /* Construct authentication header */
3541 authhdr.seq = cpu_to_be64 ( tls->tx.seq );
3542 authhdr.header.type = type;
3543 authhdr.header.version = htons ( tls->version );
3544 authhdr.header.length = htons ( record_len );
3545
3546 /* Construct and set initialisation vector */
3547 memcpy ( iv.fixed, cipherspec->fixed_iv, sizeof ( iv.fixed ) );
3548 tls_ephemeral ( tls, &authhdr, sizeof ( authhdr ), iv.rec,
3549 sizeof ( iv.rec ) );
3550 if ( ( rc = cipher_setiv ( cipher, cipherspec->cipher_ctx, &iv,
3551 sizeof ( iv ) ) ) != 0 ) {
3552 DBGC ( tls, "TLS %p could not set TX IV: %s\n",
3553 tls, strerror ( rc ) );
3554 goto err_setiv;
3555 }
3556
3557 /* Process authentication data */
3558 if ( suite->mac_len ) {
3559 tls_hmac ( cipherspec, &authhdr, plaintext, record_len,
3560 mac );
3561 }
3562 if ( is_auth_cipher ( cipher ) ) {
3563 cipher_encrypt ( cipher, cipherspec->cipher_ctx,
3564 &authhdr, NULL, sizeof ( authhdr ) );
3565 }
3566
3567 /* Calculate encryption length */
3568 encrypt_len = ( record_len + suite->mac_len );
3569 if ( is_block_cipher ( cipher ) ) {
3570 pad_len = ( ( ( cipher->blocksize - 1 ) &
3571 -( encrypt_len + 1 ) ) + 1 );
3572 } else {
3573 pad_len = 0;
3574 }
3575 encrypt_len += pad_len;
3576
3577 /* Add record header */
3578 tlshdr = iob_put ( iobuf, sizeof ( *tlshdr ) );
3579 tlshdr->type = type;
3580 tlshdr->version = htons ( tls->version );
3581 tlshdr->length = htons ( sizeof ( iv.rec ) + encrypt_len +
3582 cipher->authsize );
3583
3584 /* Add record initialisation vector, if applicable */
3585 memcpy ( iob_put ( iobuf, sizeof ( iv.rec ) ), iv.rec,
3586 sizeof ( iv.rec ) );
3587
3588 /* Copy plaintext data if necessary */
3589 ciphertext = iob_put ( iobuf, record_len );
3590 assert ( ciphertext <= plaintext );
3591 if ( encrypt_len > record_len ) {
3592 memmove ( ciphertext, plaintext, record_len );
3593 encrypt = ciphertext;
3594 } else {
3595 encrypt = plaintext;
3596 }
3597
3598 /* Add MAC, if applicable */
3599 memcpy ( iob_put ( iobuf, suite->mac_len ), mac,
3600 suite->mac_len );
3601
3602 /* Add padding, if applicable */
3603 memset ( iob_put ( iobuf, pad_len ), ( pad_len - 1 ), pad_len );
3604
3605 /* Encrypt data and append authentication tag */
3606 DBGC2 ( tls, "Sending plaintext data:\n" );
3607 DBGC2_HDA ( tls, 0, encrypt, encrypt_len );
3608 cipher_encrypt ( cipher, cipherspec->cipher_ctx, encrypt,
3609 ciphertext, encrypt_len );
3610 cipher_auth ( cipher, cipherspec->cipher_ctx,
3611 iob_put ( iobuf, cipher->authsize ) );
3612
3613 /* Move to next record */
3614 tls->tx.seq += 1;
3615 plaintext += record_len;
3616 len -= record_len;
3617
3618 } while ( len );
3619
3620 /* Send ciphertext */
3621 if ( ( rc = xfer_deliver_iob ( &tls->cipherstream,
3622 iob_disown ( iobuf ) ) ) != 0 ) {
3623 DBGC ( tls, "TLS %p could not deliver ciphertext: %s\n",
3624 tls, strerror ( rc ) );
3625 goto err_deliver;
3626 }
3627
3628 assert ( iobuf == NULL );
3629 return 0;
3630
3631 err_deliver:
3632 err_setiv:
3633 free_iob ( iobuf );
3634 return rc;
3635}
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
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:89
#define iob_put(iobuf, len)
Definition iobuf.h:125
#define iob_disown(iobuf)
Disown an I/O buffer.
Definition iobuf.h:217
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition iobuf.h:160
#define iob_unput(iobuf, len)
Definition iobuf.h:140
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:53
TLS authentication header.
Definition tls.h:164
A TLS cipher suite.
Definition tls.h:219
uint8_t fixed_iv_len
Fixed initialisation vector length.
Definition tls.h:235
struct cipher_algorithm * cipher
Bulk encryption cipher algorithm.
Definition tls.h:225
uint8_t mac_len
MAC length.
Definition tls.h:239
uint8_t record_iv_len
Record initialisation vector length.
Definition tls.h:237
struct digest_algorithm * digest
MAC digest algorithm.
Definition tls.h:227
struct tls_cipherspec active
Current cipher specification.
Definition tls.h:295
A TLS cipher specification.
Definition tls.h:279
void * fixed_iv
Fixed initialisation vector.
Definition tls.h:289
struct tls_cipher_suite * suite
Cipher suite.
Definition tls.h:281
void * cipher_ctx
Bulk encryption cipher context.
Definition tls.h:285
struct tls_tx tx
Transmit state.
Definition tls.h:559
uint16_t version
Protocol version.
Definition tls.h:548
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
uint64_t seq
Sequence number.
Definition tls.h:471
struct tls_cipherspec_pair cipherspec
Cipher specifications.
Definition tls.h:469
static void tls_ephemeral(struct tls_connection *tls, const void *info, size_t info_len, void *out, size_t len)
Generate ephemeral secret.
Definition tls.c:457
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:3404
static int tls_add_handshake(struct tls_connection *tls, const void *data, size_t len)
Add handshake record to verification hash.
Definition tls.c:1157
#define TLS_TX_BUFSIZE
TX maximum fragment length.
Definition tls.h:577
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__, tls_cipherspec_pair::active, assert, cipher_algorithm::authsize, cipher_algorithm::blocksize, tls_cipher_suite::cipher, cipher_auth(), tls_cipherspec::cipher_ctx, cipher_encrypt, cipher_setiv(), tls_tx::cipherspec, tls_connection::cipherstream, cpu_to_be64, 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, free_iob(), tls_auth_header::header, htons, iob_disown, iob_len(), iob_push, iob_put, iob_unput, is_auth_cipher(), is_block_cipher(), iv, 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_tx::seq, strerror(), tls_cipherspec::suite, tls_add_handshake(), tls_ephemeral(), tls_hmac(), tls_iob_reserved(), TLS_TX_BUFSIZE, TLS_TYPE_HANDSHAKE, tls_connection::tx, tls_header::type, type, tls_connection::version, tls_header::version, and xfer_deliver_iob().

Referenced by tls_plainstream_deliver(), tls_send_certificate(), 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 3646 of file tls.c.

3647 {
3648 struct io_buffer *iobuf;
3649 int rc;
3650
3651 /* Allocate I/O buffer */
3652 iobuf = tls_alloc_iob ( tls, len );
3653 if ( ! iobuf )
3654 return -ENOMEM_TX_PLAINTEXT;
3655 memcpy ( iob_put ( iobuf, len ), data, len );
3656
3657 /* Transmit I/O buffer */
3658 if ( ( rc = tls_send_record ( tls, type, iob_disown ( iobuf ) ) ) != 0 )
3659 return rc;
3660
3661 return 0;
3662}
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:3472
static int tls_send_record(struct tls_connection *tls, unsigned int type, struct io_buffer *iobuf)
Send plaintext record(s).
Definition tls.c:3499
#define ENOMEM_TX_PLAINTEXT
Definition tls.c:135

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(), tls_send_change_cipher(), and tls_send_handshake().

◆ tls_clear_cipher() [1/2]

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

References out.

Referenced by add_tls(), free_tls(), tls_change_cipher(), and tls_set_cipher().

◆ tls_clear_digest()

void tls_clear_digest ( struct tls_connection * tls)
static

Clear key schedule digest algorithm.

Parameters
tlsTLS connection

Definition at line 542 of file tls.c.

542 {
543 struct tls_key_schedule *key = &tls->key;
544
545 /* Set null digest algorithm */
546 key->digest = &digest_null;
547
548 /* Free any dynamic storage */
549 zfree ( key->dynamic );
550 key->dynamic = NULL;
551 key->handshake = NULL;
552 key->kdf = NULL;
553
554 /* Key schedule no longer contains any shared secret */
555 tls_clear_binding ( tls );
556 key->keyed = 0;
557}
struct digest_algorithm digest_null
Definition crypto_null.c:53
void zfree(void *ptr)
Clear and free memory.
Definition malloc.c:682
static void tls_clear_binding(struct tls_connection *tls)
Clear key schedule binding.
Definition tls.c:505

References digest_null, key, tls_connection::key, NULL, tls_clear_binding(), and zfree().

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

◆ tls_verify_handshake()

void tls_verify_handshake ( struct tls_connection * tls,
void * out )
static

Calculate handshake verification hash.

Parameters
tlsTLS connection
outOutput buffer

Calculates the digest over all handshake messages seen so far.

Definition at line 1174 of file tls.c.

1174 {
1175 struct tls_key_schedule *key = &tls->key;
1176 struct digest_algorithm *digest = key->digest;
1177 uint8_t ctx[ digest->ctxsize ];
1178
1179 memcpy ( ctx, key->handshake, sizeof ( ctx ) );
1180 digest_final ( digest, ctx, out );
1181}
struct golan_eq_context ctx
Definition CIB_PRM.h:0
static void digest_final(struct digest_algorithm *digest, void *ctx, void *out)
Definition crypto.h:305
size_t ctxsize
Context size.
Definition crypto.h:23

References ctx, digest_algorithm::ctxsize, digest_final(), key, tls_connection::key, memcpy(), and out.

Referenced by tls_generate_master_secret(), tls_new_finished(), tls_send_certificate_verify(), and tls_send_finished().

◆ tls_uint24()

unsigned long tls_uint24 ( const tls24_t * field24)
inlinestatic

Extract 24-bit field value.

Parameters
field2424-bit field
Return values
valueField value

Definition at line 251 of file tls.c.

251 {
252
253 return ( ( field24->high << 16 ) | be16_to_cpu ( field24->low ) );
254}
#define be16_to_cpu(value)
Definition byteswap.h:116
uint8_t high
High byte.
Definition tls.c:238
uint16_t low
Low word.
Definition tls.c:240

References be16_to_cpu, tls24_t::high, and tls24_t::low.

Referenced by tls_new_certificate(), tls_new_handshake(), and tls_parse_chain().

◆ tls_set_uint24()

void tls_set_uint24 ( tls24_t * field24,
unsigned long value )
static

Set 24-bit field value.

Parameters
field2424-bit field
valueField value

Definition at line 262 of file tls.c.

262 {
263
264 field24->high = ( value >> 16 );
265 field24->low = cpu_to_be16 ( value );
266}
pseudo_bit_t value[0x00020]
Definition arbel.h:2
#define cpu_to_be16(value)
Definition byteswap.h:110

References cpu_to_be16, tls24_t::high, tls24_t::low, and value.

Referenced by tls_send_certificate().

◆ 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 274 of file tls.c.

274 {
275 return ( ( ! is_pending ( &tls->client.negotiation ) ) &&
276 ( ! is_pending ( &tls->server.negotiation ) ) );
277}
static int is_pending(struct pending_operation *pending)
Check if an operation is pending.
Definition pending.h:25
struct pending_operation negotiation
Security negotiation pending operation.
Definition tls.h:505
struct tls_server server
Server state.
Definition tls.h:565
struct pending_operation negotiation
Security negotiation pending operation.
Definition tls.h:521

References tls_connection::client, is_pending(), tls_client::negotiation, tls_server::negotiation, and tls_connection::server.

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 supported version check.

Definition at line 291 of file tls.c.

291 {
292 return ( ( TLS_VERSION_MIN >= version ) ||
293 ( tls->version >= version ) );
294}
u32 version
Driver version.
Definition ath9k_hw.c:1985
#define TLS_VERSION_MIN
Minimum TLS version.
Definition crypto.h:14

References TLS_VERSION_MIN, tls_connection::version, and version.

Referenced by tls_generate_resumption_master(), tls_prf(), tls_select_cipher(), tls_send_certificate_verify(), tls_set_digest(), tls_set_kdf_master(), and tls_verify_dh_params().

◆ free_tls_session()

void free_tls_session ( struct refcnt * refcnt)
static

Free TLS session.

Parameters
refcntReference counter

Definition at line 308 of file tls.c.

308 {
309 struct tls_session *session =
311
312 /* Sanity check */
313 assert ( list_empty ( &session->conn ) );
314
315 /* Remove from list of sessions */
316 list_del ( &session->list );
317
318 /* Free dynamically-allocated resources */
319 x509_root_put ( session->root );
320 privkey_put ( session->key );
321 x509_put ( session->cert );
322 zfree ( session->ticket );
323
324 /* Free session */
325 zfree ( session );
326}
#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
A TLS session.
Definition tls.h:332
struct private_key * key
Private key.
Definition tls.h:343
struct x509_certificate * cert
Server certificate.
Definition tls.h:346
struct x509_root * root
Root of trust.
Definition tls.h:341
void * ticket
Session ticket.
Definition tls.h:352
struct list_head list
List of sessions.
Definition tls.h:336
static void x509_put(struct x509_certificate *cert)
Drop reference to X.509 certificate.
Definition x509.h:278
static void x509_root_put(struct x509_root *root)
Drop reference to X.509 root certificate list.
Definition x509.h:404

References assert, tls_session::cert, tls_session::conn, container_of, tls_session::key, tls_session::list, list_del, list_empty, privkey_put(), tls_session::root, tls_session::ticket, x509_put(), 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 333 of file tls.c.

333 {
334 struct tls_connection *tls =
336 struct tls_session *session = tls->session;
337 struct io_buffer *iobuf;
338 struct io_buffer *tmp;
339
340 /* Free dynamically-allocated resources */
341 zfree ( tls->new_session_ticket );
342 tls_clear_cipher ( tls, &tls->tx.cipherspec.active );
343 tls_clear_cipher ( tls, &tls->tx.cipherspec.pending );
344 tls_clear_cipher ( tls, &tls->rx.cipherspec.active );
345 tls_clear_cipher ( tls, &tls->rx.cipherspec.pending );
346 tls_clear_digest ( tls );
347 list_for_each_entry_safe ( iobuf, tmp, &tls->rx.data, list ) {
348 list_del ( &iobuf->list );
349 free_iob ( iobuf );
350 }
351 free_iob ( tls->rx.handshake );
352 privkey_put ( tls->client.key );
353 x509_chain_put ( tls->client.chain );
354 x509_chain_put ( tls->server.chain );
355 x509_root_put ( tls->server.root );
356
357 /* Drop reference to session */
358 assert ( list_empty ( &tls->list ) );
359 ref_put ( &session->refcnt );
360
361 /* Free TLS structure itself */
362 zfree ( tls );
363}
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:45
struct tls_cipherspec pending
Next cipher specification.
Definition tls.h:297
struct private_key * key
Private key (if used).
Definition tls.h:501
struct x509_chain * chain
Certificate chain (if used).
Definition tls.h:503
struct tls_rx rx
Receive state.
Definition tls.h:561
void * new_session_ticket
New session ticket.
Definition tls.h:538
struct tls_cipherspec_pair cipherspec
Cipher specifications.
Definition tls.h:481
struct list_head data
List of received data buffers.
Definition tls.h:491
struct io_buffer * handshake
Received handshake fragment.
Definition tls.h:493
struct x509_root * root
Root of trust.
Definition tls.h:513
struct x509_chain * chain
Certificate chain.
Definition tls.h:515
struct refcnt refcnt
Reference counter.
Definition tls.h:334
static void tls_clear_digest(struct tls_connection *tls)
Clear key schedule digest algorithm.
Definition tls.c:542
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 tls_cipherspec_pair::active, assert, tls_client::chain, tls_server::chain, tls_rx::cipherspec, tls_tx::cipherspec, tls_connection::client, container_of, tls_rx::data, 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_session_ticket, tls_cipherspec_pair::pending, 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, 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 371 of file tls.c.

371 {
372
373 /* Remove pending operations, if applicable */
376 pending_put ( &tls->server.validation );
377
378 /* Remove process */
379 process_del ( &tls->tx.process );
380
381 /* Close all interfaces */
382 intf_shutdown ( &tls->cipherstream, rc );
383 intf_shutdown ( &tls->plainstream, rc );
384 intf_shutdown ( &tls->server.validator, rc );
385
386 /* Remove from session */
387 list_del ( &tls->list );
388 INIT_LIST_HEAD ( &tls->list );
389
390 /* Destroy ephemeral master secret */
392
393 /* Resume all other connections, in case we were the lead connection */
394 tls_tx_resume_all ( tls->session );
395}
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 interface plainstream
Plaintext stream.
Definition tls.h:543
struct pending_operation validation
Certificate validation pending operation.
Definition tls.h:519
struct interface validator
Certificate validator.
Definition tls.h:517
struct process process
Transmit process.
Definition tls.h:475
static void tls_regenerate_ephemeral_master(struct tls_connection *tls)
Regenerate ephemeral master secret.
Definition tls.c:488
static void tls_tx_resume_all(struct tls_session *session)
Resume TX state machine for all connections within a session.
Definition tls.c:1925

References 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_regenerate_ephemeral_master(), 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 403 of file tls.c.

403 {
404
405 /* Send closure alert */
407
408 /* Close connection */
409 tls_close ( tls, rc );
410}
static int tls_send_alert(struct tls_connection *tls, unsigned int level, unsigned int description)
Transmit Alert record.
Definition tls.c:2406
static void tls_close(struct tls_connection *tls, int rc)
Finish with TLS connection.
Definition tls.c:371
#define TLS_ALERT_CLOSE_NOTIFY
Definition tls.h:84
#define TLS_ALERT_WARNING
Definition tls.h:80

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_generate_ephemeral_master()

int tls_generate_ephemeral_master ( struct tls_connection * tls)
static

Generate ephemeral master secret.

Parameters
tlsTLS connection
Return values
rcReturn status code

Definition at line 425 of file tls.c.

425 {
426 struct tls_key_schedule *key = &tls->key;
428 static const char salt[16] = "ephemeral master";
429 int rc;
430
431 /* Generate random bits with no additional input and without
432 * prediction resistance
433 */
434 if ( ( rc = rbg_generate ( NULL, 0, 0, key->ephemeral,
435 sizeof ( key->ephemeral ) ) ) != 0 ) {
436 DBGC ( tls, "TLS %p could not generate random data: %s\n",
437 tls, strerror ( rc ) );
438 return rc;
439 }
440
441 /* Generate ephemeral master secret */
442 hkdf_extract ( digest, salt, sizeof ( salt ), key->ephemeral,
443 sizeof ( key->ephemeral ), key->ephemeral );
444
445 return 0;
446}
void hkdf_extract(struct digest_algorithm *digest, const void *salt, size_t salt_len, const void *ikm, size_t ikm_len, void *prk)
Extract fixed-length pseudorandom key.
Definition hkdf.c:56
int rbg_generate(const void *additional, size_t additional_len, int prediction_resist, void *data, size_t len)
Generate bits using RBG.
Definition rbg.c:117
#define tls_ephemeral_algorithm
HKDF algorithm for ephemeral secrets.
Definition tls.h:367

References DBGC, hkdf_extract(), key, tls_connection::key, NULL, rbg_generate(), rc, strerror(), and tls_ephemeral_algorithm.

Referenced by add_tls().

◆ tls_ephemeral()

void tls_ephemeral ( struct tls_connection * tls,
const void * info,
size_t info_len,
void * out,
size_t len )
static

Generate ephemeral secret.

Parameters
tlsTLS connection
infoAdditional information (or NULL)
info_lenLength of additional information
outEphemeral secret to fill in
lenLength of ephemeral secret

Definition at line 457 of file tls.c.

458 {
459 struct tls_key_schedule *key = &tls->key;
461
462 /* Generate from ephemeral master secret and additional information */
463 hkdf_expand ( digest, key->ephemeral, info, info_len, out, len );
464}
u32 info
Definition ar9003_mac.h:0
void hkdf_expand(struct digest_algorithm *digest, const void *prk, const void *info, size_t info_len, void *out, size_t len)
Expand pseudorandom key.
Definition hkdf.c:95
uint8_t info_len
Reject information length.
Definition ib_mad.h:7

References hkdf_expand(), info, info_len, key, tls_connection::key, len, out, and tls_ephemeral_algorithm.

Referenced by tls_ephemeral_label(), and tls_send_record().

◆ tls_ephemeral_label()

void tls_ephemeral_label ( struct tls_connection * tls,
const char * label,
void * out,
size_t len )
static

Generate ephemeral secret from label.

Parameters
tlsTLS connection
labelSecret label
outEphemeral secret to fill in
lenLength of ephemeral secret

Definition at line 474 of file tls.c.

475 {
476
477 /* Generate from ephemeral master secret and label */
478 tls_ephemeral ( tls, label, strlen ( label ), out, len );
479 DBGC2 ( tls, "TLS %p ephemeral %s:\n", tls, label );
480 DBGC2_HDA ( tls, 0, out, len );
481}
size_t strlen(const char *src)
Get length of string.
Definition string.c:244

References DBGC2, DBGC2_HDA, len, out, strlen(), and tls_ephemeral().

Referenced by tls_agree_ephemeral(), tls_regenerate_ephemeral_master(), tls_send_client_key_exchange_pubkey(), tls_session(), tls_set_digest(), and tls_share_ephemeral().

◆ tls_clear_binding()

void tls_clear_binding ( struct tls_connection * tls)
static

Clear key schedule binding.

Parameters
tlsTLS connection

Definition at line 505 of file tls.c.

505 {
506 struct tls_key_schedule *key = &tls->key;
507
508 /* Clear any existing binding */
509 x509_put ( key->bound );
510 key->bound = NULL;
511}

References key, tls_connection::key, NULL, and x509_put().

Referenced by tls_agree_ephemeral(), tls_clear_digest(), tls_send_client_key_exchange_pubkey(), and tls_set_binding().

◆ tls_set_binding()

void tls_set_binding ( struct tls_connection * tls,
struct x509_certificate * cert )
static

Bind key schedule to a server identity.

Parameters
tlsTLS connection
certServer certificate

Definition at line 519 of file tls.c.

520 {
521 struct tls_key_schedule *key = &tls->key;
522
523 /* Clear any existing binding */
524 tls_clear_binding ( tls );
525
526 /* Refuse to bind an empty shared secret */
527 if ( ! key->keyed ) {
528 DBGC ( tls, "TLS %p refusing empty binding\n", tls );
529 return;
530 }
531
532 /* Bind to new identity */
533 key->bound = x509_get ( cert );
534 DBGC ( tls, "TLS %p bound to %s\n", tls, x509_name ( cert ) );
535}
const char * x509_name(struct x509_certificate *cert)
Get X.509 certificate display name.
Definition x509.c:147
static struct x509_certificate * x509_get(struct x509_certificate *cert)
Get reference to X.509 certificate.
Definition x509.h:267

References DBGC, key, tls_connection::key, tls_clear_binding(), x509_get(), and x509_name().

Referenced by tls_resume_secret(), tls_send_client_key_exchange_pubkey(), and tls_verify_dh_params().

◆ 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 566 of file tls.c.

567 {
568 struct tls_key_schedule *key = &tls->key;
569 size_t kdfsize;
570 size_t total;
571 void *dynamic;
572
573 /* Clear existing key schedule digest algorithm */
574 tls_clear_digest ( tls );
575
576 /* Allocate dynamic storage */
577 if ( tls_version ( tls, TLS_VERSION_TLS_1_2 ) ) {
578 kdfsize = hmac_keysize ( digest );
579 } else {
580 kdfsize = sizeof ( struct md5_sha1_hmac_keys );
581 }
582 total = ( digest->ctxsize + kdfsize );
583 dynamic = zalloc ( total );
584 if ( ! dynamic )
585 return -ENOMEM;
586
587 /* Assign storage */
588 key->dynamic = dynamic;
589 key->handshake = dynamic; dynamic += digest->ctxsize;
590 key->kdf = dynamic; dynamic += kdfsize;
591 assert ( ( key->dynamic + total ) == dynamic );
592
593 /* Store digest algorithm */
594 key->digest = digest;
595
596 /* Initialise handshake context */
597 digest_init ( digest, key->handshake );
598
599 /* Poison key derivation function master secret */
600 tls_ephemeral_label ( tls, "kdf poison", key->kdf, kdfsize );
601
602 /* Sanity checks */
603 assert ( ! key->keyed );
604 assert ( ! key->bound );
605
606 return 0;
607}
#define ENOMEM
Not enough space.
Definition errno.h:535
static size_t hmac_keysize(struct digest_algorithm *digest)
Calculate HMAC reduced key size.
Definition hmac.h:35
static void digest_init(struct digest_algorithm *digest, void *ctx)
Definition crypto.h:294
void * zalloc(size_t size)
Allocate cleared memory.
Definition malloc.c:662
An MD5+SHA1 HMAC key block.
Definition md5_sha1.h:57
struct digest_algorithm * digest
Digest algorithm.
Definition tls.h:378
void * dynamic
Dynamically-allocated storage.
Definition tls.h:457
static int tls_version(struct tls_connection *tls, unsigned int version)
Check for TLS version.
Definition tls.c:291
#define TLS_VERSION_TLS_1_2
TLS version 1.2.
Definition tls.h:49

References assert, digest_algorithm::ctxsize, tls_key_schedule::digest, digest_init(), tls_key_schedule::dynamic, ENOMEM, hmac_keysize(), key, tls_connection::key, tls_clear_digest(), tls_ephemeral_label(), tls_version(), TLS_VERSION_TLS_1_2, and zalloc().

Referenced by tls_select_cipher().

◆ tls_hmac_update_va()

void tls_hmac_update_va ( struct digest_algorithm * digest,
void * ctx,
va_list args )
static

Update HMAC with a list of ( data, len ) pairs.

Parameters
digestHash function to use
ctxHMAC context
args( data, len ) pairs of data, terminated by NULL

Definition at line 616 of file tls.c.

617 {
618 void *data;
619 size_t len;
620
621 while ( ( data = va_arg ( args, void * ) ) ) {
622 len = va_arg ( args, size_t );
623 hmac_update ( digest, ctx, data, len );
624 }
625}
static void hmac_update(struct digest_algorithm *digest, void *ctx, const void *data, size_t len)
Update HMAC.
Definition hmac.h:62
#define va_arg(ap, type)
Definition stdarg.h:9

References ctx, data, hmac_update(), len, and va_arg.

Referenced by tls_p_hash_va().

◆ tls_p_hash_va()

void tls_p_hash_va ( struct tls_connection * tls,
struct digest_algorithm * digest,
const void * hkey,
void * out,
size_t out_len,
va_list seeds )
static

Generate secure pseudo-random data using a single hash function.

Parameters
tlsTLS connection
digestHash function to use
hkeyHMAC key
outOutput buffer
out_lenLength of output buffer
seeds( data, len ) pairs of seed data, terminated by NULL

Definition at line 637 of file tls.c.

639 {
640 uint8_t ctx[ hmac_ctxsize ( digest ) ];
641 uint8_t ctx_partial[ sizeof ( ctx ) ];
642 uint8_t a[digest->digestsize];
643 uint8_t out_tmp[digest->digestsize];
644 size_t frag_len = digest->digestsize;
645 va_list tmp;
646
647 /* Calculate A(1) */
648 hmac_init_key ( digest, ctx, hkey );
649 va_copy ( tmp, seeds );
650 tls_hmac_update_va ( digest, ctx, tmp );
651 va_end ( tmp );
652 hmac_final ( digest, ctx, a );
653 DBGC2 ( tls, "TLS %p %s A(1):\n", tls, digest->name );
654 DBGC2_HD ( tls, &a, sizeof ( a ) );
655
656 /* Generate as much data as required */
657 while ( out_len ) {
658
659 /* Calculate output portion */
660 hmac_init_key ( digest, ctx, hkey );
661 hmac_update ( digest, ctx, a, sizeof ( a ) );
662 memcpy ( ctx_partial, ctx, sizeof ( ctx_partial ) );
663 va_copy ( tmp, seeds );
664 tls_hmac_update_va ( digest, ctx, tmp );
665 va_end ( tmp );
666 hmac_final ( digest, ctx, out_tmp );
667
668 /* Copy output */
669 if ( frag_len > out_len )
670 frag_len = out_len;
671 memcpy ( out, out_tmp, frag_len );
672 DBGC2 ( tls, "TLS %p %s output:\n", tls, digest->name );
673 DBGC2_HD ( tls, out, frag_len );
674
675 /* Calculate A(i) */
676 hmac_final ( digest, ctx_partial, a );
677 DBGC2 ( tls, "TLS %p %s A(n):\n", tls, digest->name );
678 DBGC2_HD ( tls, &a, sizeof ( a ) );
679
680 out += frag_len;
681 out_len -= frag_len;
682 }
683}
#define DBGC2_HD(...)
Definition compiler.h:549
void hmac_final(struct digest_algorithm *digest, void *ctx, void *hmac)
Finalise HMAC.
Definition hmac.c:124
void hmac_init_key(struct digest_algorithm *digest, void *ctx, const void *key)
Initialise HMAC from reduced key.
Definition hmac.c:82
static size_t hmac_ctxsize(struct digest_algorithm *digest)
Calculate HMAC context size.
Definition hmac.h:48
#define va_copy(dest, src)
Definition stdarg.h:11
#define va_end(ap)
Definition stdarg.h:10
__builtin_va_list va_list
Definition stdarg.h:7
const char * name
Algorithm name.
Definition crypto.h:21
static void tls_hmac_update_va(struct digest_algorithm *digest, void *ctx, va_list args)
Update HMAC with a list of ( data, len ) pairs.
Definition tls.c:616

References ctx, DBGC2, DBGC2_HD, digest_algorithm::digestsize, hmac_ctxsize(), hmac_final(), hmac_init_key(), hmac_update(), memcpy(), digest_algorithm::name, out, tls_hmac_update_va(), tmp, va_copy, and va_end.

Referenced by tls_prf().

◆ tls_prf()

void tls_prf ( struct tls_connection * tls,
void * out,
size_t out_len,
... )
static

Generate secure pseudo-random data.

Parameters
tlsTLS connection
outOutput buffer
out_lenLength of output buffer
...( data, len ) pairs of seed data, terminated by NULL

Definition at line 693 of file tls.c.

694 {
695 struct tls_key_schedule *key = &tls->key;
696 struct md5_sha1_hmac_keys *hkeys;
697 va_list seeds;
698 va_list tmp;
699 uint8_t buf[out_len];
700 unsigned int i;
701
702 va_start ( seeds, out_len );
703
704 if ( tls_version ( tls, TLS_VERSION_TLS_1_2 ) ) {
705
706 /* Use P_Hash for TLSv1.2 and later */
707 tls_p_hash_va ( tls, key->digest, key->kdf,
708 out, out_len, seeds );
709
710 } else {
711
712 /* Use combination of P_MD5 and P_SHA-1 for TLSv1.1
713 * and earlier
714 */
715 hkeys = key->kdf;
716
717 /* Calculate MD5 portion */
718 va_copy ( tmp, seeds );
719 tls_p_hash_va ( tls, &md5_algorithm, hkeys->md5,
720 out, out_len, seeds );
721 va_end ( tmp );
722
723 /* Calculate SHA1 portion */
724 va_copy ( tmp, seeds );
725 tls_p_hash_va ( tls, &sha1_algorithm, hkeys->sha1,
726 buf, out_len, seeds );
727 va_end ( tmp );
728
729 /* XOR the two portions together into the final output buffer */
730 for ( i = 0 ; i < out_len ; i++ )
731 *( ( uint8_t * ) out + i ) ^= buf[i];
732 }
733
734 va_end ( seeds );
735}
struct digest_algorithm md5_algorithm
struct digest_algorithm sha1_algorithm
#define va_start(ap, last)
Definition stdarg.h:8
uint8_t md5[MD5_BLOCK_SIZE]
MD5 HMAC key.
Definition md5_sha1.h:59
uint8_t sha1[SHA1_BLOCK_SIZE]
SHA-1 HMAC key.
Definition md5_sha1.h:61
static void tls_p_hash_va(struct tls_connection *tls, struct digest_algorithm *digest, const void *hkey, void *out, size_t out_len, va_list seeds)
Generate secure pseudo-random data using a single hash function.
Definition tls.c:637

References key, tls_connection::key, md5_sha1_hmac_keys::md5, md5_algorithm, out, md5_sha1_hmac_keys::sha1, sha1_algorithm, tls_p_hash_va(), tls_version(), TLS_VERSION_TLS_1_2, tmp, va_copy, va_end, and va_start.

◆ tls_set_kdf_master()

void tls_set_kdf_master ( struct tls_connection * tls,
const void * secret,
size_t secret_len )
static

Set key derivation function master secret.

Parameters
tlsTLS connection
secretSecret
secret_lenLength of secret

Definition at line 757 of file tls.c.

758 {
759 struct tls_key_schedule *key = &tls->key;
760 struct digest_algorithm *digest = key->digest;
761 uint8_t ctx[ hmac_ctxsize ( digest ) ];
762 struct md5_sha1_hmac_keys *hkeys;
763 size_t subsecret_len;
764 const void *md5_secret;
765 const void *sha1_secret;
766
767 DBGC2 ( tls, "TLS %p KDF secret:\n", tls );
768 DBGC2_HD ( tls, secret, secret_len );
769
770 if ( tls_version ( tls, TLS_VERSION_TLS_1_2 ) ) {
771
772 /* Set HMAC key for TLSv1.2 and later */
773 hmac_key ( digest, ctx, secret, secret_len, key->kdf );
774
775 } else {
776
777 /* Set MD5+SHA1 HMAC keys for TLSv1.1 and earlier */
778 hkeys = key->kdf;
779 assert ( key->digest == &md5_sha1_algorithm );
780 assert ( sizeof ( ctx ) >= hmac_ctxsize ( &md5_algorithm ) );
781 assert ( sizeof ( ctx ) >= hmac_ctxsize ( &sha1_algorithm ) );
782
783 /* Split secret into two, with an overlap of up to one byte */
784 subsecret_len = ( ( secret_len + 1 ) / 2 );
785 md5_secret = secret;
786 sha1_secret = ( secret + secret_len - subsecret_len );
787
788 /* Set MD5 and SHA-1 HMAC keys */
789 hmac_key ( &md5_algorithm, ctx, md5_secret, subsecret_len,
790 hkeys->md5 );
791 hmac_key ( &sha1_algorithm, ctx, sha1_secret, subsecret_len,
792 hkeys->sha1 );
793 }
794}
void hmac_key(struct digest_algorithm *digest, void *ctx, const void *secret, size_t len, void *key)
Construct HMAC reduced key.
Definition hmac.c:59
struct digest_algorithm md5_sha1_algorithm
Hybrid MD5+SHA1 digest algorithm.
Definition md5_sha1.c:84

References assert, ctx, DBGC2, DBGC2_HD, hmac_ctxsize(), hmac_key(), key, tls_connection::key, md5_sha1_hmac_keys::md5, md5_algorithm, md5_sha1_algorithm, md5_sha1_hmac_keys::sha1, sha1_algorithm, tls_version(), and TLS_VERSION_TLS_1_2.

Referenced by tls_agree_ephemeral(), tls_generate_master_secret(), tls_resume_secret(), and tls_send_client_key_exchange_pubkey().

◆ tls_share_ephemeral()

int tls_share_ephemeral ( struct tls_connection * tls,
void * public )
static

Share ephemeral public key.

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

Definition at line 803 of file tls.c.

803 {
804 struct tls_key_schedule *key = &tls->key;
805 struct tls_named_group *group = key->group;
806 struct exchange_algorithm *exchange = group->exchange;
807 size_t privsize = exchange->privsize;
808 struct {
809 uint8_t private[privsize];
810 } tmp;
811 int rc;
812
813 /* (Re)generate ephemeral private key */
814 tls_ephemeral_label ( tls, exchange->name, tmp.private, privsize );
815
816 /* Derive public key */
817 if ( ( rc = exchange_share ( exchange, tmp.private, public ) ) != 0 ) {
818 DBGC ( tls, "TLS %p could not share ephemeral key: %s\n",
819 tls, strerror ( rc ) );
820 goto err_share;
821 }
822
823 err_share:
824 memset ( &tmp, 0, sizeof ( tmp ) );
825 return rc;
826}
uint16_t group
Type of event.
Definition ena.h:1
static int exchange_share(struct exchange_algorithm *exchange, const void *private, void *public)
Definition crypto.h:397
A key exchange algorithm.
Definition crypto.h:210
size_t privsize
Private key size.
Definition crypto.h:214
const char * name
Algorithm name.
Definition crypto.h:212
A TLS named group.
Definition tls.h:254

References DBGC, exchange_share(), group, key, tls_connection::key, memset(), exchange_algorithm::name, exchange_algorithm::privsize, rc, strerror(), tls_ephemeral_label(), and tmp.

Referenced by tls_send_client_key_exchange_dhe(), and tls_send_client_key_exchange_ecdhe().

◆ tls_agree_ephemeral()

int tls_agree_ephemeral ( struct tls_connection * tls,
const void * partner,
size_t partner_len,
int strip )
static

Agree ephemeral public key (i.e.

pre-master secret)

Parameters
tlsTLS connection
partnerPartner public key
partner_lenLength of partner public key
stripStrip/pad leading zeros
Return values
rcReturn status code

Definition at line 837 of file tls.c.

839 {
840 struct tls_key_schedule *key = &tls->key;
841 struct tls_named_group *group = key->group;
842 struct exchange_algorithm *exchange = group->exchange;
843 size_t privsize = exchange->privsize;
844 size_t pubsize = exchange->pubsize;
845 size_t sharedsize = exchange->sharedsize;
846 struct {
847 uint8_t private[privsize];
849 uint8_t shared[sharedsize];
850 } *tmp;
851 size_t pad_len;
852 size_t shared_len;
853 uint8_t *shared;
854 int rc;
855
856 /* Allocate working space */
857 tmp = zalloc ( sizeof ( *tmp ) );
858 if ( ! tmp ) {
859 rc = -ENOMEM;
860 goto err_alloc;
861 }
862
863 /* (Re)generate ephemeral private key */
864 tls_ephemeral_label ( tls, exchange->name, tmp->private, privsize );
865
866 /* Zero-pad partner key if needed */
867 if ( partner_len > pubsize ) {
868 DBGC ( tls, "TLS %p partner key too long:\n", tls );
869 DBGC_HDA ( tls, 0, partner, partner_len );
871 goto err_partner_len;
872 }
873 pad_len = ( pubsize - partner_len );
874 if ( pad_len && ( ! strip ) ) {
875 DBGC ( tls, "TLS %p partner key too short:\n", tls );
876 DBGC_HDA ( tls, 0, partner, partner_len );
878 goto err_partner_len;
879 }
880 memcpy ( ( tmp->partner + pad_len ), partner, partner_len );
881
882 /* Agree shared secret */
883 if ( ( rc = exchange_agree ( exchange, tmp->private, tmp->partner,
884 tmp->shared ) ) != 0 ) {
885 DBGC ( tls, "TLS %p could not agree shared key: %s\n",
886 tls, strerror ( rc ) );
887 goto err_agree;
888 }
889
890 /* Strip leading zeros if needed */
891 shared = tmp->shared;
892 shared_len = sharedsize;
893 while ( strip && shared_len && ( ! *shared ) ) {
894 shared++;
895 shared_len--;
896 }
897
898 /* Set key derivation function secret to the shared secret */
899 DBGC ( tls, "TLS %p pre-master secret:\n", tls );
900 DBGC_HDA ( tls, 0, shared, shared_len );
901 tls_set_kdf_master ( tls, shared, shared_len );
902
903 /* Key derivation function secret has been overwritten with a
904 * value that was not derived from its previous value, and so
905 * is no longer bound to the server's identity.
906 */
907 tls_clear_binding ( tls );
908
909 /* Key schedule now contains shared secret key material */
910 key->keyed = 1;
911
912 err_agree:
913 err_partner_len:
914 memset ( tmp, 0, sizeof ( *tmp ) );
915 zfree ( tmp );
916 err_alloc:
917 return rc;
918}
struct eth_slow_lacp_entity_tlv partner
Partner information.
Definition eth_slow.h:5
#define DBGC_HDA(...)
Definition compiler.h:531
static int exchange_agree(struct exchange_algorithm *exchange, const void *private, const void *partner, void *shared)
Definition crypto.h:403
size_t sharedsize
Shared secret size.
Definition crypto.h:218
size_t pubsize
Public key size.
Definition crypto.h:216
#define EINVAL_KEY_EXCHANGE
Definition tls.c:111
static void tls_set_kdf_master(struct tls_connection *tls, const void *secret, size_t secret_len)
Set key derivation function master secret.
Definition tls.c:757

References DBGC, DBGC_HDA, EINVAL_KEY_EXCHANGE, ENOMEM, exchange_agree(), group, key, tls_connection::key, memcpy(), memset(), exchange_algorithm::name, partner, exchange_algorithm::privsize, exchange_algorithm::pubsize, rc, exchange_algorithm::sharedsize, strerror(), tls_clear_binding(), tls_ephemeral_label(), tls_set_kdf_master(), tmp, zalloc(), and zfree().

Referenced by tls_new_server_key_exchange_dhe(), and tls_new_server_key_exchange_ecdhe().

◆ tls_generate_master_secret()

void tls_generate_master_secret ( struct tls_connection * tls)
static

Generate master secret.

Parameters
tlsTLS connection

The client and server random values must already be known.

Definition at line 927 of file tls.c.

927 {
928 struct tls_key_schedule *key = &tls->key;
929 struct digest_algorithm *digest = key->digest;
930 uint8_t digest_out[ digest->digestsize ];
931 uint8_t master_secret[48];
932
933 /* Sanity checks */
934 assert ( key->keyed );
935 assert ( key->bound );
936
937 /* Generate handshake digest */
938 tls_verify_handshake ( tls, digest_out );
939
940 /* Show inputs */
941 DBGC ( tls, "TLS %p client random bytes:\n", tls );
942 DBGC_HD ( tls, &tls->client.random, sizeof ( tls->client.random ) );
943 DBGC ( tls, "TLS %p server random bytes:\n", tls );
944 DBGC_HD ( tls, &tls->server.random, sizeof ( tls->server.random ) );
945 DBGC ( tls, "TLS %p session hash:\n", tls );
946 DBGC_HD ( tls, digest_out, sizeof ( digest_out ) );
947
948 /* Generate master secret */
949 if ( tls->extended_master_secret ) {
950 tls_prf_label ( tls, master_secret, sizeof ( master_secret ),
951 "extended master secret",
952 digest_out, sizeof ( digest_out ) );
953 } else {
954 tls_prf_label ( tls, master_secret, sizeof ( master_secret ),
955 "master secret",
956 &tls->client.random,
957 sizeof ( tls->client.random ),
958 &tls->server.random,
959 sizeof ( tls->server.random ) );
960 }
961
962 /* Show output */
963 DBGC ( tls, "TLS %p generated %smaster secret:\n", tls,
964 ( tls->extended_master_secret ? "extended ": "" ) );
965 DBGC_HD ( tls, master_secret, sizeof ( master_secret ) );
966
967 /* Set key derivation function secret to the master secret */
968 tls_set_kdf_master ( tls, master_secret, sizeof ( master_secret ) );
969}
#define DBGC_HD(...)
Definition compiler.h:532
int extended_master_secret
Extended master secret flag.
Definition tls.h:552
uint8_t random[32]
Random bytes.
Definition tls.h:511
#define tls_prf_label(tls, out, out_len, label,...)
Generate secure pseudo-random data.
Definition tls.c:746
static void tls_verify_handshake(struct tls_connection *tls, void *out)
Calculate handshake verification hash.
Definition tls.c:1174

References assert, tls_connection::client, DBGC, DBGC_HD, digest_algorithm::digestsize, tls_connection::extended_master_secret, key, tls_connection::key, tls_client::random, tls_server::random, tls_connection::server, tls_prf_label, tls_set_kdf_master(), and tls_verify_handshake().

Referenced by tls_send_client_key_exchange().

◆ tls_generate_keys()

int tls_generate_keys ( struct tls_connection * tls)
static

Generate key material.

Parameters
tlsTLS connection

The master secret must already be known.

Definition at line 978 of file tls.c.

978 {
979 struct tls_cipherspec *tx_cipherspec = &tls->tx.cipherspec.pending;
980 struct tls_cipherspec *rx_cipherspec = &tls->rx.cipherspec.pending;
981 size_t hash_size = tx_cipherspec->suite->mac_len;
982 size_t key_size = tx_cipherspec->suite->key_len;
983 size_t iv_size = tx_cipherspec->suite->fixed_iv_len;
984 size_t total = ( 2 * ( hash_size + key_size + iv_size ) );
985 uint8_t key_block[total];
986 uint8_t *key;
987 int rc;
988
989 /* Sanity checks */
990 assert ( tls->key.keyed );
991 assert ( tls->key.bound );
992
993 /* Generate key block */
994 tls_prf_label ( tls, key_block, sizeof ( key_block ), "key expansion",
995 &tls->server.random, sizeof ( tls->server.random ),
996 &tls->client.random, sizeof ( tls->client.random ) );
997
998 /* Split key block into portions */
999 key = key_block;
1000
1001 /* TX MAC secret */
1002 memcpy ( tx_cipherspec->mac_secret, key, hash_size );
1003 DBGC ( tls, "TLS %p TX MAC secret:\n", tls );
1004 DBGC_HD ( tls, key, hash_size );
1005 key += hash_size;
1006
1007 /* RX MAC secret */
1008 memcpy ( rx_cipherspec->mac_secret, key, hash_size );
1009 DBGC ( tls, "TLS %p RX MAC secret:\n", tls );
1010 DBGC_HD ( tls, key, hash_size );
1011 key += hash_size;
1012
1013 /* TX key */
1014 if ( ( rc = cipher_setkey ( tx_cipherspec->suite->cipher,
1015 tx_cipherspec->cipher_ctx,
1016 key, key_size ) ) != 0 ) {
1017 DBGC ( tls, "TLS %p could not set TX key: %s\n",
1018 tls, strerror ( rc ) );
1019 return rc;
1020 }
1021 DBGC ( tls, "TLS %p TX key:\n", tls );
1022 DBGC_HD ( tls, key, key_size );
1023 key += key_size;
1024
1025 /* RX key */
1026 if ( ( rc = cipher_setkey ( rx_cipherspec->suite->cipher,
1027 rx_cipherspec->cipher_ctx,
1028 key, key_size ) ) != 0 ) {
1029 DBGC ( tls, "TLS %p could not set TX key: %s\n",
1030 tls, strerror ( rc ) );
1031 return rc;
1032 }
1033 DBGC ( tls, "TLS %p RX key:\n", tls );
1034 DBGC_HD ( tls, key, key_size );
1035 key += key_size;
1036
1037 /* TX initialisation vector */
1038 memcpy ( tx_cipherspec->fixed_iv, key, iv_size );
1039 DBGC ( tls, "TLS %p TX IV:\n", tls );
1040 DBGC_HD ( tls, key, iv_size );
1041 key += iv_size;
1042
1043 /* RX initialisation vector */
1044 memcpy ( rx_cipherspec->fixed_iv, key, iv_size );
1045 DBGC ( tls, "TLS %p RX IV:\n", tls );
1046 DBGC_HD ( tls, key, iv_size );
1047 key += iv_size;
1048
1049 assert ( ( key_block + total ) == key );
1050
1051 return 0;
1052}
static int cipher_setkey(struct cipher_algorithm *cipher, void *ctx, const void *key, size_t keylen)
Definition crypto.h:310
uint8_t key_len
Key length.
Definition tls.h:233
void * mac_secret
MAC secret.
Definition tls.h:287
struct x509_certificate * bound
Server identity to which the schedule has been bound (if any).
Definition tls.h:455
int keyed
Schedule holds secret key material.
Definition tls.h:393

References assert, tls_key_schedule::bound, tls_cipher_suite::cipher, tls_cipherspec::cipher_ctx, cipher_setkey(), tls_rx::cipherspec, tls_tx::cipherspec, tls_connection::client, DBGC, DBGC_HD, tls_cipherspec::fixed_iv, tls_cipher_suite::fixed_iv_len, key, tls_connection::key, tls_cipher_suite::key_len, tls_key_schedule::keyed, tls_cipher_suite::mac_len, tls_cipherspec::mac_secret, memcpy(), tls_cipherspec_pair::pending, tls_client::random, tls_server::random, rc, tls_connection::rx, tls_connection::server, strerror(), tls_cipherspec::suite, tls_prf_label, and tls_connection::tx.

Referenced by tls_new_server_hello(), and tls_send_client_key_exchange().

◆ tls_generate_resumption_master()

void tls_generate_resumption_master ( struct tls_connection * tls)
static

Generate resumption master secret.

Parameters
tlsTLS connection

Definition at line 1059 of file tls.c.

1059 {
1060 struct tls_session *session = tls->session;
1061 struct tls_key_schedule *key = &tls->key;
1062 struct digest_algorithm *digest = key->digest;
1063 struct md5_sha1_hmac_keys *hkeys;
1064 union {
1065 uint8_t opaque[48];
1066 struct {
1067 uint8_t md5[24];
1068 uint8_t sha1[24];
1069 } __attribute__ (( packed ));
1070 } *secret;
1071
1072 /* Sanity checks */
1073 assert ( key->keyed );
1074 assert ( key->bound );
1075 assert ( x509_is_valid ( key->bound, tls->server.root ) );
1076 assert ( sizeof ( *secret ) <=
1077 sizeof ( session->resumption_master_secret ) );
1078 secret = ( ( void * ) session->resumption_master_secret );
1079
1080 if ( tls_version ( tls, TLS_VERSION_TLS_1_2 ) ) {
1081
1082 /* For TLSv1.2, the pre-master secret may be any
1083 * length but the master secret is fixed at 48 bytes.
1084 * This is smaller than the block size for all
1085 * supported digest algorithms. The HMAC key
1086 * constructed from the master secret will therefore
1087 * be just the zero-padded master secret value. We
1088 * can therefore preserve just these first 48 bytes of
1089 * the KDF master secret (ignoring the zero padding up
1090 * to the digest block size).
1091 */
1092 assert ( sizeof ( *secret ) <= hmac_keysize ( digest ) );
1093 memcpy ( secret, key->kdf, sizeof ( *secret ) );
1094 session->resumption_master_secret_len = sizeof ( *secret );
1095
1096 } else {
1097
1098 /* For TLSv1.1 and earlier, the master secret is again
1099 * fixed at 48 bytes, but will be split as 24 bytes in
1100 * each of the MD5 and SHA-1 HMAC keys.
1101 */
1102 assert ( key->digest == &md5_sha1_algorithm );
1103 assert ( sizeof ( secret->md5 ) <=
1105 assert ( sizeof ( secret->sha1 ) <=
1107 hkeys = key->kdf;
1108 memcpy ( secret->md5, hkeys->md5, sizeof ( secret->md5 ) );
1109 memcpy ( secret->sha1, hkeys->sha1, sizeof ( secret->sha1 ) );
1110 session->resumption_master_secret_len = sizeof ( *secret );
1111 }
1112}
uint8_t resumption_master_secret[48]
Resumption master secret.
Definition tls.h:356
size_t resumption_master_secret_len
Length of resumption master secret.
Definition tls.h:358
int x509_is_valid(struct x509_certificate *cert, struct x509_root *root)
Check if X.509 certificate is valid.
Definition x509.c:1313

References __attribute__, assert, hmac_keysize(), key, tls_connection::key, md5_sha1_hmac_keys::md5, md5_algorithm, md5_sha1_algorithm, memcpy(), tls_session::resumption_master_secret, tls_session::resumption_master_secret_len, tls_server::root, tls_connection::server, tls_connection::session, md5_sha1_hmac_keys::sha1, sha1_algorithm, tls_version(), TLS_VERSION_TLS_1_2, and x509_is_valid().

Referenced by tls_new_finished().

◆ tls_resume_secret()

void tls_resume_secret ( struct tls_connection * tls)
static

Resume from resumption master secret.

Parameters
tlsTLS connection

Definition at line 1119 of file tls.c.

1119 {
1120 struct tls_session *session = tls->session;
1121 struct tls_key_schedule *key = &tls->key;
1122 size_t len = session->resumption_master_secret_len;
1123
1124 /* For TLSv1.2 and earlier, the resumption master secret is
1125 * just the original master secret value.
1126 */
1128
1129 /* If the resumption master secret was non-empty, then the key
1130 * schedule now contains a shared secret that is already bound
1131 * to the server's identity.
1132 *
1133 * If the resumption master secret was empty (which should not
1134 * be possible if this function is called), then the key
1135 * schedule no longer contains any shared secret.
1136 */
1137 assert ( len );
1138 key->keyed = len;
1139 tls_set_binding ( tls, session->cert );
1140}
static void tls_set_binding(struct tls_connection *tls, struct x509_certificate *cert)
Bind key schedule to a server identity.
Definition tls.c:519

References assert, tls_session::cert, key, tls_connection::key, len, tls_session::resumption_master_secret, tls_session::resumption_master_secret_len, tls_connection::session, tls_set_binding(), and tls_set_kdf_master().

Referenced by tls_new_server_hello().

◆ tls_add_handshake()

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

Add handshake record to verification hash.

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

Definition at line 1157 of file tls.c.

1158 {
1159 struct tls_key_schedule *key = &tls->key;
1160 struct digest_algorithm *digest = key->digest;
1161
1162 digest_update ( digest, key->handshake, data, len );
1163 return 0;
1164}
static void digest_update(struct digest_algorithm *digest, void *ctx, const void *data, size_t len)
Definition crypto.h:299

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

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

◆ 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 1208 of file tls.c.

1208 {
1209 struct tls_cipher_suite *suite;
1210
1211 /* Identify cipher suite */
1213 if ( suite->code == cipher_suite )
1214 return suite;
1215 }
1216
1217 return NULL;
1218}
uint16_t code
Numeric code (in network-endian order).
Definition tls.h:231
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
Definition tables.h:386
#define TLS_CIPHER_SUITES
TLS cipher suite table.
Definition tls.h:243

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

Referenced by tls_select_cipher().

◆ tls_clear_cipher() [2/2]

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

Clear cipher suite.

Parameters
cipherspecTLS cipher specification

Definition at line 1225 of file tls.c.

1226 {
1227
1228 zfree ( cipherspec->dynamic );
1229 memset ( cipherspec, 0, sizeof ( *cipherspec ) );
1230 cipherspec->suite = &tls_cipher_suite_null;
1231}
void * dynamic
Dynamically-allocated storage.
Definition tls.h:283
struct tls_cipher_suite tls_cipher_suite_null
Null cipher suite.
Definition tls.c:1191

References __unused, tls_cipherspec::dynamic, memset(), tls_cipherspec::suite, tls_cipher_suite_null, and zfree().

◆ tls_set_cipher()

int tls_set_cipher ( struct tls_connection * tls,
struct tls_cipherspec * cipherspec,
struct tls_cipher_suite * suite )
static

Set cipher suite.

Parameters
tlsTLS connection
cipherspecTLS cipher specification
suiteCipher suite
Return values
rcReturn status code

Definition at line 1241 of file tls.c.

1243 {
1244 struct cipher_algorithm *cipher = suite->cipher;
1245 size_t total;
1246 void *dynamic;
1247
1248 /* Clear out old cipher contents, if any */
1249 tls_clear_cipher ( tls, cipherspec );
1250
1251 /* Allocate dynamic storage */
1252 total = ( cipher->ctxsize + suite->mac_len + suite->fixed_iv_len );
1253 dynamic = zalloc ( total );
1254 if ( ! dynamic ) {
1255 DBGC ( tls, "TLS %p could not allocate %zd bytes for crypto "
1256 "context\n", tls, total );
1257 return -ENOMEM_CONTEXT;
1258 }
1259
1260 /* Assign storage */
1261 cipherspec->dynamic = dynamic;
1262 cipherspec->cipher_ctx = dynamic; dynamic += cipher->ctxsize;
1263 cipherspec->mac_secret = dynamic; dynamic += suite->mac_len;
1264 cipherspec->fixed_iv = dynamic; dynamic += suite->fixed_iv_len;
1265 assert ( ( cipherspec->dynamic + total ) == dynamic );
1266
1267 /* Store parameters */
1268 cipherspec->suite = suite;
1269
1270 return 0;
1271}
size_t ctxsize
Context size.
Definition crypto.h:62
#define ENOMEM_CONTEXT
Definition tls.c:123

References assert, tls_cipher_suite::cipher, tls_cipherspec::cipher_ctx, cipher_algorithm::ctxsize, DBGC, tls_cipherspec::dynamic, ENOMEM_CONTEXT, tls_cipherspec::fixed_iv, tls_cipher_suite::fixed_iv_len, tls_cipher_suite::mac_len, tls_cipherspec::mac_secret, tls_cipherspec::suite, tls_clear_cipher(), and zalloc().

Referenced by tls_select_cipher().

◆ tls_select_cipher()

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

Select next cipher suite.

Parameters
tlsTLS connection
cipher_suiteCipher suite specification
Return values
rcReturn status code

Definition at line 1280 of file tls.c.

1281 {
1282 struct tls_cipher_suite *suite;
1283 struct digest_algorithm *digest;
1284 int rc;
1285
1286 /* Identify cipher suite */
1287 suite = tls_find_cipher_suite ( cipher_suite );
1288 if ( ! suite ) {
1289 DBGC ( tls, "TLS %p does not support cipher %04x\n",
1290 tls, ntohs ( cipher_suite ) );
1291 return -ENOTSUP_CIPHER;
1292 }
1293
1294 /* Set key schedule digest algorithm */
1295 digest = ( tls_version ( tls, TLS_VERSION_TLS_1_2 ) ?
1296 suite->handshake : &md5_sha1_algorithm );
1297 if ( ( rc = tls_set_digest ( tls, digest ) ) != 0 )
1298 return rc;
1299
1300 /* Set ciphers */
1301 if ( ( rc = tls_set_cipher ( tls, &tls->tx.cipherspec.pending,
1302 suite ) ) != 0 )
1303 return rc;
1304 if ( ( rc = tls_set_cipher ( tls, &tls->rx.cipherspec.pending,
1305 suite ) ) != 0 )
1306 return rc;
1307
1308 DBGC ( tls, "TLS %p selected %s-%s-%s-%d-%s\n", tls,
1309 suite->exchange->name, suite->pubkey->name,
1310 suite->cipher->name, ( suite->key_len * 8 ),
1311 suite->digest->name );
1312
1313 return 0;
1314}
#define ntohs(value)
Definition byteswap.h:137
const char * name
Algorithm name.
Definition crypto.h:60
const char * name
Algorithm name.
Definition crypto.h:144
struct pubkey_algorithm * pubkey
Public-key encryption algorithm.
Definition tls.h:223
struct tls_key_exchange_algorithm * exchange
Key exchange algorithm.
Definition tls.h:221
struct digest_algorithm * handshake
Handshake digest algorithm (for TLSv1.2 and above).
Definition tls.h:229
const char * name
Algorithm name.
Definition tls.h:198
#define ENOTSUP_CIPHER
Definition tls.c:151
static int tls_set_digest(struct tls_connection *tls, struct digest_algorithm *digest)
Set key schedule digest algorithm.
Definition tls.c:566
static int tls_set_cipher(struct tls_connection *tls, struct tls_cipherspec *cipherspec, struct tls_cipher_suite *suite)
Set cipher suite.
Definition tls.c:1241
static struct tls_cipher_suite * tls_find_cipher_suite(unsigned int cipher_suite)
Identify cipher suite.
Definition tls.c:1208

References tls_cipher_suite::cipher, tls_rx::cipherspec, tls_tx::cipherspec, DBGC, tls_cipher_suite::digest, ENOTSUP_CIPHER, tls_cipher_suite::exchange, tls_cipher_suite::handshake, tls_cipher_suite::key_len, md5_sha1_algorithm, cipher_algorithm::name, digest_algorithm::name, pubkey_algorithm::name, tls_key_exchange_algorithm::name, ntohs, tls_cipherspec_pair::pending, tls_cipher_suite::pubkey, rc, tls_connection::rx, tls_find_cipher_suite(), tls_set_cipher(), tls_set_digest(), tls_version(), TLS_VERSION_TLS_1_2, and tls_connection::tx.

Referenced by tls_new_server_hello().

◆ tls_change_cipher()

int tls_change_cipher ( struct tls_connection * tls,
struct tls_cipherspec_pair * pair )
static

Activate next cipher suite.

Parameters
tlsTLS connection
pairCipher specification pair
Return values
rcReturn status code

Definition at line 1323 of file tls.c.

1324 {
1325
1326 /* Sanity check */
1327 if ( pair->pending.suite == &tls_cipher_suite_null ) {
1328 DBGC ( tls, "TLS %p refusing to use null cipher\n", tls );
1329 return -ENOTSUP_NULL;
1330 }
1331
1332 tls_clear_cipher ( tls, &pair->active );
1333 memswap ( &pair->active, &pair->pending, sizeof ( pair->active ) );
1334 return 0;
1335}
void * memswap(void *first, void *second, size_t len)
Swap memory regions.
Definition string.c:154
#define ENOTSUP_NULL
Definition tls.c:155

References tls_cipherspec_pair::active, DBGC, ENOTSUP_NULL, memswap(), tls_cipherspec_pair::pending, tls_cipherspec::suite, tls_cipher_suite_null, and tls_clear_cipher().

Referenced by tls_new_change_cipher(), and tls_tx_step().

◆ 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 1356 of file tls.c.

1357 {
1358 struct tls_signature_hash_algorithm *sig_hash;
1359
1360 /* Identify signature and hash algorithm */
1362 if ( ( sig_hash->pubkey == pubkey ) &&
1363 ( sig_hash->digest == digest ) ) {
1364 return sig_hash;
1365 }
1366 }
1367
1368 return NULL;
1369}
A TLS signature algorithm.
Definition tls.h:301
struct pubkey_algorithm * pubkey
Public-key algorithm.
Definition tls.h:305
struct digest_algorithm * digest
Digest algorithm.
Definition tls.h:303
#define TLS_SIG_HASH_ALGORITHMS
TLS signature hash algorithm table.
Definition tls.h:317

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 1378 of file tls.c.

1378 {
1379 struct tls_signature_hash_algorithm *sig_hash;
1380
1381 /* Identify signature and hash algorithm */
1383 if ( sig_hash->code == code )
1384 return sig_hash;
1385 }
1386
1387 return NULL;
1388}
static unsigned int code
Definition hyperv.h:26
uint16_t code
Numeric code (in network-endian order).
Definition tls.h:309

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

Referenced by tls_verify_dh_params().

◆ 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 1404 of file tls.c.

1404 {
1405 struct tls_named_group *group;
1406
1407 /* Identify named group */
1409 if ( group->code && ( group->code == named_group ) )
1410 return group;
1411 }
1412
1413 return NULL;
1414}
#define TLS_NAMED_GROUPS
TLS named group table.
Definition tls.h:262

References for_each_table_entry, group, NULL, and TLS_NAMED_GROUPS.

Referenced by tls_new_server_key_exchange_ecdhe().

◆ tls_find_param_group()

struct tls_named_group * tls_find_param_group ( const void * dh_p,
size_t dh_p_len,
const void * dh_g,
size_t dh_g_len )
static

Identify named key exchange group by Diffie-Hellman parameters.

Parameters
dh_pPrime modulus
dh_p_lenLength of prime modulus
dh_gGenerator
dh_g_lenLength of generator
Return values
groupNamed group, or NULL

Definition at line 1426 of file tls.c.

1427 {
1428 struct tls_named_group *group;
1429
1430 /* Identify named group by parameters */
1432 if ( is_ffdhe ( group->exchange ) &&
1433 ffdhe_has_params ( group->exchange, dh_p, dh_p_len,
1434 dh_g, dh_g_len ) ) {
1435 return group;
1436 }
1437 }
1438
1439 return NULL;
1440}
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 ffdhe_has_params(), for_each_table_entry, group, is_ffdhe(), NULL, and TLS_NAMED_GROUPS.

Referenced by tls_new_server_key_exchange_dhe().

◆ tls_verify_dh_params()

int tls_verify_dh_params ( struct tls_connection * tls,
const void * data,
size_t len,
size_t param_len )
static

Verify Diffie-Hellman parameter signature.

Parameters
tlsTLS connection
dataServer Key Exchange handshake record
lenLength of Server Key Exchange handshake record
param_lenLength of Diffie-Hellman parameters
Return values
rcReturn status code

Definition at line 1451 of file tls.c.

1452 {
1453 struct tls_cipherspec *cipherspec = &tls->tx.cipherspec.pending;
1454 struct tls_signature_hash_algorithm *sig_hash;
1455 struct x509_certificate *cert;
1456 struct pubkey_algorithm *pubkey;
1457 struct digest_algorithm *digest;
1458 int use_sig_hash = tls_version ( tls, TLS_VERSION_TLS_1_2 );
1459 const struct {
1460 uint16_t sig_hash[use_sig_hash];
1461 uint16_t signature_len;
1462 uint8_t signature[0];
1463 } __attribute__ (( packed )) *sig;
1464 struct asn1_cursor signature;
1465 size_t remaining;
1466 int rc;
1467
1468 /* Identify server certificate */
1469 cert = x509_first ( tls->server.chain );
1470 if ( ! cert ) {
1471 DBGC ( tls, "TLS %p has no server certificate\n", tls );
1472 return -ENOENT_CERT;
1473 }
1474
1475 /* Signature follows parameters */
1476 assert ( param_len <= len );
1477 sig = ( data + param_len );
1478 remaining = ( len - param_len );
1479
1480 /* Parse signature from ServerKeyExchange */
1481 if ( ( sizeof ( *sig ) > remaining ) ||
1482 ( ntohs ( sig->signature_len ) > ( remaining -
1483 sizeof ( *sig ) ) ) ) {
1484 DBGC ( tls, "TLS %p received underlength ServerKeyExchange\n",
1485 tls );
1486 DBGC_HDA ( tls, 0, data, len );
1487 return -EINVAL_KEY_EXCHANGE;
1488 }
1489 signature.data = sig->signature;
1490 signature.len = ntohs ( sig->signature_len );
1491
1492 /* Identify signature and hash algorithm */
1493 if ( use_sig_hash ) {
1494 sig_hash = tls_find_signature_hash ( sig->sig_hash[0] );
1495 if ( ! sig_hash ) {
1496 DBGC ( tls, "TLS %p unsupported signature hash "
1497 "%#04x\n", tls, sig->sig_hash[0] );
1498 return -ENOTSUP_SIG_HASH;
1499 }
1500 pubkey = sig_hash->pubkey;
1501 digest = sig_hash->digest;
1502 DBGC ( tls, "TLS %p using signature hash %s-%s\n",
1503 tls, pubkey->name, digest->name );
1504 if ( sig_hash->algorithm !=
1505 cert->subject.public_key.algorithm ) {
1506 DBGC ( tls, "TLS %p cannot use %s public key\n", tls,
1508 return -EPERM_KEY_EXCHANGE;
1509 }
1510 } else {
1511 pubkey = cipherspec->suite->pubkey;
1512 digest = &md5_sha1_algorithm;
1513 }
1514
1515 /* Verify signature */
1516 {
1517 uint8_t ctx[digest->ctxsize];
1518 uint8_t hash[digest->digestsize];
1519
1520 /* Calculate digest */
1521 digest_init ( digest, ctx );
1522 digest_update ( digest, ctx, &tls->client.random,
1523 sizeof ( tls->client.random ) );
1524 digest_update ( digest, ctx, tls->server.random,
1525 sizeof ( tls->server.random ) );
1526 digest_update ( digest, ctx, data, param_len );
1527 digest_final ( digest, ctx, hash );
1528
1529 /* Verify signature */
1530 if ( ( rc = pubkey_verify ( pubkey,
1531 &cert->subject.public_key.raw,
1532 digest, hash,
1533 &signature ) ) != 0 ) {
1534 DBGC ( tls, "TLS %p ServerKeyExchange failed "
1535 "verification\n", tls );
1536 DBGC_HDA ( tls, 0, data, len );
1537 return -EPERM_KEY_EXCHANGE;
1538 }
1539 }
1540
1541 /* The verified signature indicates the server's intention to
1542 * delegate authority to the shared secret key material. The
1543 * shared secret is therefore bound to the server's identity.
1544 */
1545 tls_set_binding ( tls, cert );
1546
1547 return 0;
1548}
u8 sig
Definition CIB_PRM.h:15
u8 signature
CPU signature.
Definition CIB_PRM.h:7
pseudo_bit_t hash[0x00010]
Definition arbel.h:2
unsigned short uint16_t
Definition stdint.h:11
static int pubkey_verify(struct pubkey_algorithm *pubkey, const struct asn1_cursor *key, struct digest_algorithm *digest, const void *value, const struct asn1_cursor *signature)
Definition crypto.h:383
const char * name
Name.
Definition asn1.h:416
An ASN.1 object cursor.
Definition asn1.h:21
A public key algorithm.
Definition crypto.h:142
struct asn1_algorithm * algorithm
Required certificate OID-identified algorithm.
Definition tls.h:307
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 asn1_cursor raw
Raw public key information.
Definition x509.h:52
struct x509_public_key public_key
Public key information.
Definition x509.h:66
#define EPERM_KEY_EXCHANGE
Definition tls.c:187
#define ENOTSUP_SIG_HASH
Definition tls.c:159
#define ENOENT_CERT
Definition tls.c:119
static struct tls_signature_hash_algorithm * tls_find_signature_hash(unsigned int code)
Find TLS signature and hash algorithm.
Definition tls.c:1378
static struct x509_certificate * x509_first(struct x509_chain *chain)
Get first certificate in X.509 certificate chain.
Definition x509.h:311

References __attribute__, tls_signature_hash_algorithm::algorithm, x509_public_key::algorithm, assert, tls_server::chain, tls_tx::cipherspec, tls_connection::client, ctx, digest_algorithm::ctxsize, data, DBGC, DBGC_HDA, tls_signature_hash_algorithm::digest, digest_final(), digest_init(), digest_update(), digest_algorithm::digestsize, EINVAL_KEY_EXCHANGE, ENOENT_CERT, ENOTSUP_SIG_HASH, EPERM_KEY_EXCHANGE, hash, len, md5_sha1_algorithm, asn1_algorithm::name, digest_algorithm::name, pubkey_algorithm::name, ntohs, tls_cipherspec_pair::pending, tls_cipher_suite::pubkey, tls_signature_hash_algorithm::pubkey, pubkey_verify(), x509_subject::public_key, tls_client::random, tls_server::random, x509_public_key::raw, rc, tls_connection::server, sig, signature, x509_certificate::subject, tls_cipherspec::suite, tls_find_signature_hash(), tls_set_binding(), tls_version(), TLS_VERSION_TLS_1_2, tls_connection::tx, and x509_first().

Referenced by tls_new_server_key_exchange_dhe(), and tls_new_server_key_exchange_ecdhe().

◆ tls_new_server_key_exchange_pubkey()

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

Receive new Server Key Exchange record using public key transport.

Parameters
tlsTLS connection
dataServer Key Exchange handshake record
lenLength of Server Key Exchange handshake record
Return values
rcReturn status code

Definition at line 1558 of file tls.c.

1559 {
1560
1561 /* Should never be received */
1562 DBGC ( tls, "TLS %p received unexpected ServerKeyExchange:\n", tls );
1563 DBGC_HDA ( tls, 0, data, len );
1564 return -EPROTO;
1565}
#define EPROTO
Protocol error.
Definition errno.h:625

References data, DBGC, DBGC_HDA, EPROTO, and len.

◆ tls_send_client_key_exchange_pubkey()

int tls_send_client_key_exchange_pubkey ( struct tls_connection * tls)
static

Transmit Client Key Exchange record using public key exchange.

Parameters
tlsTLS connection
Return values
rcReturn status code

Definition at line 1573 of file tls.c.

1573 {
1574 struct tls_cipherspec *cipherspec = &tls->tx.cipherspec.pending;
1575 struct tls_key_schedule *key = &tls->key;
1576 struct pubkey_algorithm *pubkey = cipherspec->suite->pubkey;
1577 struct x509_certificate *cert;
1578 struct {
1580 uint8_t random[46];
1581 } __attribute__ (( packed )) pre_master_secret;
1582 struct asn1_cursor cursor = {
1583 .data = &pre_master_secret,
1584 .len = sizeof ( pre_master_secret ),
1585 };
1586 struct asn1_builder builder = { NULL, 0 };
1587 int rc;
1588
1589 /* Generate pre-master secret */
1590 pre_master_secret.version = htons ( TLS_VERSION_MAX );
1591 tls_ephemeral_label ( tls, "classic pre-master",
1592 &pre_master_secret.random,
1593 sizeof ( pre_master_secret.random ) );
1594 tls_set_kdf_master ( tls, &pre_master_secret,
1595 sizeof ( pre_master_secret ) );
1596
1597 /* Key derivation function secret has been overwritten with a
1598 * value that was not derived from its previous value, and so
1599 * is no longer bound to the server's identity.
1600 */
1601 tls_clear_binding ( tls );
1602
1603 /* Key schedule now contains shared secret key material */
1604 key->keyed = 1;
1605
1606 /* Identify server certificate */
1607 cert = x509_first ( tls->server.chain );
1608 if ( ! cert ) {
1609 DBGC ( tls, "TLS %p has no server certificate\n", tls );
1610 rc = -ENOENT_CERT;
1611 goto err_cert;
1612 }
1613
1614 /* Encrypt pre-master secret using server's public key */
1615 if ( ( rc = pubkey_encrypt ( pubkey, &cert->subject.public_key.raw,
1616 &cursor, &builder ) ) != 0 ) {
1617 DBGC ( tls, "TLS %p could not encrypt pre-master secret: %s\n",
1618 tls, strerror ( rc ) );
1619 goto err_encrypt;
1620 }
1621
1622 /* Construct Client Key Exchange record */
1623 {
1624 struct {
1625 uint32_t type_length;
1626 uint16_t encrypted_pre_master_secret_len;
1627 } __attribute__ (( packed )) header;
1628
1629 header.type_length =
1631 htonl ( builder.len + sizeof ( header ) -
1632 sizeof ( header.type_length ) ) );
1633 header.encrypted_pre_master_secret_len = htons ( builder.len );
1634
1635 if ( ( rc = asn1_prepend_raw ( &builder, &header,
1636 sizeof ( header ) ) ) != 0 ) {
1637 DBGC ( tls, "TLS %p could not construct Client Key "
1638 "Exchange: %s\n", tls, strerror ( rc ) );
1639 goto err_prepend;
1640 }
1641 }
1642
1643 /* Transmit Client Key Exchange record */
1644 if ( ( rc = tls_send_handshake ( tls, builder.data,
1645 builder.len ) ) != 0 ) {
1646 goto err_send;
1647 }
1648
1649 /* Shared secret has now been incorporated into the handshake
1650 * digest. It can be decrypted only with access to the
1651 * certificate's private key, and has thereby been bound to
1652 * the server's identity.
1653 */
1654 tls_set_binding ( tls, cert );
1655
1656 err_send:
1657 err_prepend:
1658 err_encrypt:
1659 zfree ( builder.data );
1660 err_cert:
1661 return rc;
1662}
unsigned int uint32_t
Definition stdint.h:12
int asn1_prepend_raw(struct asn1_builder *builder, const void *data, size_t len)
Prepend raw data to ASN.1 builder.
Definition asn1.c:1019
#define TLS_VERSION_MAX
Maximum TLS version.
Definition crypto.h:17
struct ena_llq_option header
Header locations.
Definition ena.h:5
#define htonl(value)
Definition byteswap.h:134
#define cpu_to_le32(value)
Definition byteswap.h:108
static int pubkey_encrypt(struct pubkey_algorithm *pubkey, const struct asn1_cursor *key, const struct asn1_cursor *plaintext, struct asn1_builder *ciphertext)
Definition crypto.h:362
long int random(void)
Generate a pseudo-random number between 0 and 2147483647L or 2147483562?
Definition random.c:32
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
unsigned int version
Version.
Definition x509.h:233
static int tls_send_handshake(struct tls_connection *tls, const void *data, size_t len)
Transmit Handshake record.
Definition tls.c:1963
#define TLS_CLIENT_KEY_EXCHANGE
Definition tls.h:76

References __attribute__, asn1_prepend_raw(), tls_server::chain, tls_tx::cipherspec, cpu_to_le32, asn1_builder::data, DBGC, ENOENT_CERT, header, htonl, htons, key, tls_connection::key, asn1_builder::len, NULL, tls_cipherspec_pair::pending, tls_cipher_suite::pubkey, pubkey_encrypt(), x509_subject::public_key, random(), x509_public_key::raw, rc, tls_connection::server, strerror(), x509_certificate::subject, tls_cipherspec::suite, tls_clear_binding(), TLS_CLIENT_KEY_EXCHANGE, tls_ephemeral_label(), tls_send_handshake(), tls_set_binding(), tls_set_kdf_master(), TLS_VERSION_MAX, tls_connection::tx, version, x509_first(), and zfree().

◆ tls_new_server_key_exchange_dhe()

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

Receive new Server Key Exchange record using DHE key exchange.

Parameters
tlsTLS connection
dataServer Key Exchange handshake record
lenLength of Server Key Exchange handshake record
Return values
rcReturn status code

Definition at line 1679 of file tls.c.

1680 {
1681 struct tls_named_group *group;
1682 struct exchange_algorithm *exchange;
1683 const struct {
1684 uint16_t len;
1685 uint8_t data[0];
1686 } __attribute__ (( packed )) *dh_val[3];
1687 typeof ( dh_val[0] ) dh_p;
1688 typeof ( dh_val[1] ) dh_g;
1689 typeof ( dh_val[2] ) dh_ys;
1690 const void *param;
1691 size_t remaining;
1692 size_t frag_len;
1693 size_t param_len;
1694 unsigned int i;
1695 int rc;
1696
1697 /* Parse ServerKeyExchange */
1698 param = data;
1699 remaining = len;
1700 for ( i = 0 ; i < ( sizeof ( dh_val ) / sizeof ( dh_val[0] ) ) ; i++ ){
1701 dh_val[i] = param;
1702 if ( ( sizeof ( *dh_val[i] ) > remaining ) ||
1703 ( ntohs ( dh_val[i]->len ) > ( remaining -
1704 sizeof ( *dh_val[i] ) ) )){
1705 DBGC ( tls, "TLS %p received underlength "
1706 "ServerKeyExchange\n", tls );
1707 DBGC_HDA ( tls, 0, data, len );
1708 return -EINVAL_KEY_EXCHANGE;
1709 }
1710 frag_len = ( sizeof ( *dh_val[i] ) + ntohs ( dh_val[i]->len ));
1711 param += frag_len;
1712 remaining -= frag_len;
1713 }
1714 param_len = ( len - remaining );
1715
1716 /* Identify named group */
1717 dh_p = dh_val[0];
1718 dh_g = dh_val[1];
1719 dh_ys = dh_val[2];
1720 group = tls_find_param_group ( dh_p->data, ntohs ( dh_p->len ),
1721 dh_g->data, ntohs ( dh_g->len ) );
1722 if ( ! group ) {
1723 DBGC ( tls, "TLS %p unsupported %d-bit group:\n",
1724 tls, ( 8 * ntohs ( dh_p->len ) ) );
1725 DBGC_HDA ( tls, 0, data, len );
1726 return -ENOTSUP_GROUP;
1727 }
1728 tls->key.group = group;
1729 exchange = group->exchange;
1730 DBGC ( tls, "TLS %p using named group %s\n", tls, exchange->name );
1731
1732 /* Generate pre-master secret */
1733 if ( ( rc = tls_agree_ephemeral ( tls, dh_ys->data,
1734 ntohs ( dh_ys->len ), 1 ) ) != 0 ) {
1735 return rc;
1736 }
1737
1738 /* Verify parameter signature */
1739 if ( ( rc = tls_verify_dh_params ( tls, data, len, param_len ) ) != 0 )
1740 return rc;
1741
1742 return 0;
1743}
typeof(acpi_finder=acpi_find)
ACPI table finder.
Definition acpi.c:48
struct hv_monitor_parameter param[4][32]
Parameters.
Definition hyperv.h:13
struct tls_named_group * group
Named key exchange group.
Definition tls.h:380
static int tls_verify_dh_params(struct tls_connection *tls, const void *data, size_t len, size_t param_len)
Verify Diffie-Hellman parameter signature.
Definition tls.c:1451
#define ENOTSUP_GROUP
Definition tls.c:167
static int tls_agree_ephemeral(struct tls_connection *tls, const void *partner, size_t partner_len, int strip)
Agree ephemeral public key (i.e.
Definition tls.c:837
static struct tls_named_group * tls_find_param_group(const void *dh_p, size_t dh_p_len, const void *dh_g, size_t dh_g_len)
Identify named key exchange group by Diffie-Hellman parameters.
Definition tls.c:1426

References __attribute__, data, DBGC, DBGC_HDA, EINVAL_KEY_EXCHANGE, ENOTSUP_GROUP, group, tls_key_schedule::group, tls_connection::key, len, exchange_algorithm::name, ntohs, param, rc, tls_agree_ephemeral(), tls_find_param_group(), tls_verify_dh_params(), and typeof().

◆ tls_send_client_key_exchange_dhe()

int tls_send_client_key_exchange_dhe ( struct tls_connection * tls)
static

Transmit Client Key Exchange record using DHE key exchange.

Parameters
tlsTLS connection
Return values
rcReturn status code

Definition at line 1751 of file tls.c.

1751 {
1752 struct tls_key_schedule *key = &tls->key;
1753 struct tls_named_group *group = key->group;
1754 struct exchange_algorithm *exchange = group->exchange;
1755 size_t pubsize = exchange->pubsize;
1756 struct {
1757 uint32_t type_length;
1758 uint16_t dh_xs_len;
1759 uint8_t dh_xs[pubsize];
1760 } __attribute__ (( packed )) *key_xchg;
1761 int rc;
1762
1763 /* Allocate space */
1764 key_xchg = malloc ( sizeof ( *key_xchg ) );
1765 if ( ! key_xchg ) {
1766 rc = -ENOMEM;
1767 goto err_alloc;
1768 }
1769
1770 /* Generate Client Key Exchange record */
1771 key_xchg->type_length =
1773 htonl ( sizeof ( *key_xchg ) -
1774 sizeof ( key_xchg->type_length ) ) );
1775 key_xchg->dh_xs_len = htons ( sizeof ( key_xchg->dh_xs ) );
1776 if ( ( rc = tls_share_ephemeral ( tls, key_xchg->dh_xs ) ) != 0 )
1777 goto err_share;
1778
1779 /* Transmit Client Key Exchange record */
1780 if ( ( rc = tls_send_handshake ( tls, key_xchg,
1781 sizeof ( *key_xchg ) ) ) !=0 ) {
1782 goto err_send_handshake;
1783 }
1784
1785 err_send_handshake:
1786 err_share:
1787 zfree ( key_xchg );
1788 err_alloc:
1789 return rc;
1790}
void * malloc(size_t size)
Allocate memory.
Definition malloc.c:621
static int tls_share_ephemeral(struct tls_connection *tls, void *public)
Share ephemeral public key.
Definition tls.c:803

References __attribute__, cpu_to_le32, ENOMEM, group, htonl, htons, key, tls_connection::key, malloc(), exchange_algorithm::pubsize, rc, TLS_CLIENT_KEY_EXCHANGE, tls_send_handshake(), tls_share_ephemeral(), and zfree().

◆ tls_new_server_key_exchange_ecdhe()

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

Receive new Server Key Exchange record using ECDHE key exchange.

Parameters
tlsTLS connection
dataServer Key Exchange handshake record
lenLength of Server Key Exchange handshake record
Return values
rcReturn status code

Definition at line 1807 of file tls.c.

1808 {
1809 struct tls_named_group *group;
1810 struct exchange_algorithm *exchange;
1811 const struct {
1812 uint8_t curve_type;
1813 uint16_t named_group;
1814 uint8_t public_len;
1815 uint8_t public[0];
1816 } __attribute__ (( packed )) *ecdh = data;
1817 size_t param_len;
1818 int rc;
1819
1820 /* Parse ServerKeyExchange record */
1821 if ( ( sizeof ( *ecdh ) > len ) ||
1822 ( ecdh->public_len > ( len - sizeof ( *ecdh ) ) ) ) {
1823 DBGC ( tls, "TLS %p received underlength ServerKeyExchange\n",
1824 tls );
1825 DBGC_HDA ( tls, 0, data, len );
1826 return -EINVAL_KEY_EXCHANGE;
1827 }
1828 param_len = ( sizeof ( *ecdh ) + ecdh->public_len );
1829
1830 /* Identify named group */
1831 if ( ecdh->curve_type != TLS_NAMED_CURVE_TYPE ) {
1832 DBGC ( tls, "TLS %p unsupported curve type %d\n",
1833 tls, ecdh->curve_type );
1834 DBGC_HDA ( tls, 0, data, len );
1835 return -ENOTSUP_GROUP;
1836 }
1837 group = tls_find_named_group ( ecdh->named_group );
1838 if ( ! group ) {
1839 DBGC ( tls, "TLS %p unsupported named group %d\n",
1840 tls, ntohs ( ecdh->named_group ) );
1841 DBGC_HDA ( tls, 0, data, len );
1842 return -ENOTSUP_GROUP;
1843 }
1844 tls->key.group = group;
1845 exchange = group->exchange;
1846 DBGC ( tls, "TLS %p using named group %s\n", tls, exchange->name );
1847
1848 /* Generate pre-master secret */
1849 if ( ( rc = tls_agree_ephemeral ( tls, ecdh->public,
1850 ecdh->public_len, 0 ) ) != 0 ) {
1851 return rc;
1852 }
1853
1854 /* Verify parameter signature */
1855 if ( ( rc = tls_verify_dh_params ( tls, data, len, param_len ) ) != 0 )
1856 return rc;
1857
1858 return 0;
1859}
static struct tls_named_group * tls_find_named_group(unsigned int named_group)
Identify named key exchange group.
Definition tls.c:1404
#define TLS_NAMED_CURVE_TYPE
TLS named curve type.
Definition tls.h:251

References __attribute__, data, DBGC, DBGC_HDA, EINVAL_KEY_EXCHANGE, ENOTSUP_GROUP, group, tls_key_schedule::group, tls_connection::key, len, exchange_algorithm::name, ntohs, rc, tls_agree_ephemeral(), tls_find_named_group(), TLS_NAMED_CURVE_TYPE, and tls_verify_dh_params().

◆ tls_send_client_key_exchange_ecdhe()

int tls_send_client_key_exchange_ecdhe ( struct tls_connection * tls)
static

Transmit Client Key Exchange record using ECDHE key exchange.

Parameters
tlsTLS connection
Return values
rcReturn status code

Definition at line 1867 of file tls.c.

1867 {
1868 struct tls_key_schedule *key = &tls->key;
1869 struct tls_named_group *group = key->group;
1870 struct exchange_algorithm *exchange = group->exchange;
1871 size_t pubsize = exchange->pubsize;
1872 struct {
1873 uint32_t type_length;
1874 uint8_t public_len;
1875 uint8_t public[pubsize];
1876 } __attribute__ (( packed )) key_xchg;
1877 int rc;
1878
1879 /* Generate Client Key Exchange record */
1880 key_xchg.type_length =
1882 htonl ( sizeof ( key_xchg ) -
1883 sizeof ( key_xchg.type_length ) ) );
1884 key_xchg.public_len = sizeof ( key_xchg.public );
1885 if ( ( rc = tls_share_ephemeral ( tls, key_xchg.public ) ) != 0 )
1886 return rc;
1887
1888 /* Transmit Client Key Exchange record */
1889 if ( ( rc = tls_send_handshake ( tls, &key_xchg,
1890 sizeof ( key_xchg ) ) ) !=0 ) {
1891 return rc;
1892 }
1893
1894 return 0;
1895}

References __attribute__, cpu_to_le32, group, htonl, key, tls_connection::key, exchange_algorithm::pubsize, rc, TLS_CLIENT_KEY_EXCHANGE, tls_send_handshake(), and tls_share_ephemeral().

◆ tls_tx_resume()

void tls_tx_resume ( struct tls_connection * tls)
static

Resume TX state machine.

Parameters
tlsTLS connection

Definition at line 1916 of file tls.c.

1916 {
1917 process_add ( &tls->tx.process );
1918}
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_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 1937 of file tls.c.

1937 {
1938
1939 /* Sanity check */
1940 assert ( ! tls->tx.pending );
1941 assert ( ! is_pending ( &tls->client.negotiation ) );
1942 assert ( ! is_pending ( &tls->server.negotiation ) );
1943 assert ( ! is_pending ( &tls->server.validation ) );
1944
1945 /* Reset ephemeral master secret */
1947
1948 /* (Re)start negotiation */
1950 tls_tx_resume ( tls );
1951 pending_get ( &tls->client.negotiation );
1952 pending_get ( &tls->server.negotiation );
1953}
void pending_get(struct pending_operation *pending)
Mark an operation as pending.
Definition pending.c:46
unsigned int pending
Pending transmissions.
Definition tls.h:473
@ TLS_TX_CLIENT_HELLO
Definition tls.h:187

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

Referenced by add_tls(), and tls_new_hello_request().

◆ tls_client_hello()

int tls_client_hello ( struct tls_connection * tls,
int(* action )(struct tls_connection *tls, const void *data, size_t len) )
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 1977 of file tls.c.

1980 {
1981 struct tls_session *session = tls->session;
1982 size_t name_len = strlen ( session->name );
1983 struct {
1984 uint16_t type;
1985 uint16_t len;
1986 struct {
1987 uint16_t len;
1988 struct {
1989 uint8_t type;
1990 uint16_t len;
1991 uint8_t name[name_len];
1992 } __attribute__ (( packed )) list[1];
1993 } __attribute__ (( packed )) data;
1994 } __attribute__ (( packed )) *server_name_ext;
1995 struct {
1996 uint16_t type;
1997 uint16_t len;
1998 struct {
1999 uint8_t max;
2000 } __attribute__ (( packed )) data;
2001 } __attribute__ (( packed )) *max_fragment_length_ext;
2002 struct {
2003 uint16_t type;
2004 uint16_t len;
2005 struct {
2006 uint16_t len;
2008 } __attribute__ (( packed )) data;
2009 } __attribute__ (( packed )) *signature_algorithms_ext;
2010 struct {
2011 uint16_t type;
2012 uint16_t len;
2013 struct {
2014 uint8_t len;
2016 sizeof ( tls->verify.client ) :0 ];
2017 } __attribute__ (( packed )) data;
2018 } __attribute__ (( packed )) *renegotiation_info_ext;
2019 struct {
2020 uint16_t type;
2021 uint16_t len;
2022 struct {
2023 uint8_t data[session->ticket_len];
2024 } __attribute__ (( packed )) data;
2025 } __attribute__ (( packed )) *session_ticket_ext;
2026 struct {
2027 uint16_t type;
2028 uint16_t len;
2029 struct {
2030 uint16_t len;
2032 } __attribute__ (( packed )) data;
2033 } __attribute__ (( packed )) *named_group_ext;
2034 struct {
2035 uint16_t type;
2036 uint16_t len;
2037 } __attribute__ (( packed )) *extended_master_secret_ext;
2038 struct {
2039 typeof ( *server_name_ext ) server_name;
2040 typeof ( *max_fragment_length_ext ) max_fragment_length;
2041 typeof ( *signature_algorithms_ext ) signature_algorithms;
2042 typeof ( *renegotiation_info_ext ) renegotiation_info;
2043 typeof ( *session_ticket_ext ) session_ticket;
2044 typeof ( *extended_master_secret_ext ) extended_master_secret;
2045 typeof ( *named_group_ext )
2046 named_group[TLS_NUM_NAMED_GROUPS ? 1 : 0];
2047 } __attribute__ (( packed )) *extensions;
2048 struct {
2049 uint32_t type_length;
2051 uint8_t random[32];
2052 uint8_t session_id_len;
2053 uint8_t session_id[tls->session_id_len];
2054 uint16_t cipher_suite_len;
2055 uint16_t cipher_suites[TLS_NUM_CIPHER_SUITES];
2056 uint8_t compression_methods_len;
2057 uint8_t compression_methods[1];
2058 uint16_t extensions_len;
2059 typeof ( *extensions ) extensions;
2060 } __attribute__ (( packed )) hello;
2061 struct tls_cipher_suite *suite;
2062 struct tls_signature_hash_algorithm *sighash;
2063 struct tls_named_group *group;
2064 unsigned int i;
2065
2066 /* Construct record */
2067 memset ( &hello, 0, sizeof ( hello ) );
2068 hello.type_length = ( cpu_to_le32 ( TLS_CLIENT_HELLO ) |
2069 htonl ( sizeof ( hello ) -
2070 sizeof ( hello.type_length ) ) );
2071 hello.version = htons ( TLS_VERSION_MAX );
2072 memcpy ( &hello.random, &tls->client.random, sizeof ( hello.random ) );
2073 hello.session_id_len = tls->session_id_len;
2074 memcpy ( hello.session_id, tls->session_id,
2075 sizeof ( hello.session_id ) );
2076 hello.cipher_suite_len = htons ( sizeof ( hello.cipher_suites ) );
2077 i = 0 ; for_each_table_entry ( suite, TLS_CIPHER_SUITES )
2078 hello.cipher_suites[i++] = suite->code;
2079 hello.compression_methods_len = sizeof ( hello.compression_methods );
2080 hello.extensions_len = htons ( sizeof ( hello.extensions ) );
2081 extensions = &hello.extensions;
2082
2083 /* Construct server name extension */
2084 server_name_ext = &extensions->server_name;
2085 server_name_ext->type = htons ( TLS_SERVER_NAME );
2086 server_name_ext->len = htons ( sizeof ( server_name_ext->data ) );
2087 server_name_ext->data.len
2088 = htons ( sizeof ( server_name_ext->data.list ) );
2089 server_name_ext->data.list[0].type = TLS_SERVER_NAME_HOST_NAME;
2090 server_name_ext->data.list[0].len
2091 = htons ( sizeof ( server_name_ext->data.list[0].name ) );
2092 memcpy ( server_name_ext->data.list[0].name, session->name,
2093 sizeof ( server_name_ext->data.list[0].name ) );
2094
2095 /* Construct maximum fragment length extension */
2096 max_fragment_length_ext = &extensions->max_fragment_length;
2097 max_fragment_length_ext->type = htons ( TLS_MAX_FRAGMENT_LENGTH );
2098 max_fragment_length_ext->len
2099 = htons ( sizeof ( max_fragment_length_ext->data ) );
2100 max_fragment_length_ext->data.max = TLS_MAX_FRAGMENT_LENGTH_VALUE;
2101
2102 /* Construct supported signature algorithms extension */
2103 signature_algorithms_ext = &extensions->signature_algorithms;
2104 signature_algorithms_ext->type = htons ( TLS_SIGNATURE_ALGORITHMS );
2105 signature_algorithms_ext->len
2106 = htons ( sizeof ( signature_algorithms_ext->data ) );
2107 signature_algorithms_ext->data.len
2108 = htons ( sizeof ( signature_algorithms_ext->data.code ) );
2110 signature_algorithms_ext->data.code[i++] = sighash->code;
2111
2112 /* Construct renegotiation information extension */
2113 renegotiation_info_ext = &extensions->renegotiation_info;
2114 renegotiation_info_ext->type = htons ( TLS_RENEGOTIATION_INFO );
2115 renegotiation_info_ext->len
2116 = htons ( sizeof ( renegotiation_info_ext->data ) );
2117 renegotiation_info_ext->data.len
2118 = sizeof ( renegotiation_info_ext->data.data );
2119 memcpy ( renegotiation_info_ext->data.data, tls->verify.client,
2120 sizeof ( renegotiation_info_ext->data.data ) );
2121
2122 /* Construct session ticket extension */
2123 session_ticket_ext = &extensions->session_ticket;
2124 session_ticket_ext->type = htons ( TLS_SESSION_TICKET );
2125 session_ticket_ext->len
2126 = htons ( sizeof ( session_ticket_ext->data ) );
2127 memcpy ( session_ticket_ext->data.data, session->ticket,
2128 sizeof ( session_ticket_ext->data.data ) );
2129
2130 /* Construct extended master secret extension */
2131 extended_master_secret_ext = &extensions->extended_master_secret;
2132 extended_master_secret_ext->type
2134 extended_master_secret_ext->len = 0;
2135
2136 /* Construct named groups extension, if applicable */
2137 if ( sizeof ( extensions->named_group ) ) {
2138 named_group_ext = &extensions->named_group[0];
2139 named_group_ext->type = htons ( TLS_NAMED_GROUP );
2140 named_group_ext->len
2141 = htons ( sizeof ( named_group_ext->data ) );
2142 named_group_ext->data.len
2143 = htons ( sizeof ( named_group_ext->data.code ) );
2145 if ( group->code )
2146 named_group_ext->data.code[i++] = group->code;
2147 }
2149 }
2150
2151 return action ( tls, &hello, sizeof ( hello ) );
2152}
#define max(x, y)
Definition ath.h:41
uint16_t hello
Hello time.
Definition stp.h:27
struct tls_verify_data verify
Verification data.
Definition tls.h:554
size_t session_id_len
Length of session ID.
Definition tls.h:536
uint8_t session_id[32]
Session ID.
Definition tls.h:534
int secure_renegotiation
Secure renegotiation flag.
Definition tls.h:550
const char * name
Server name.
Definition tls.h:339
size_t ticket_len
Length of session ticket.
Definition tls.h:354
uint8_t client[12]
Client verification data.
Definition tls.h:174
#define TLS_NUM_CIPHER_SUITES
Number of supported cipher suites.
Definition tls.c:1199
#define TLS_NUM_SIG_HASH_ALGORITHMS
Number of supported signature and hash algorithms.
Definition tls.c:1345
#define TLS_NUM_NAMED_GROUPS
Number of non-anonymous TLS named groups.
Definition tls.h:273
#define TLS_EXTENDED_MASTER_SECRET
Definition tls.h:155
#define TLS_RENEGOTIATION_INFO
Definition tls.h:161
#define TLS_MAX_FRAGMENT_LENGTH_VALUE
Advertised maximum fragment length.
Definition tls.h:569
#define TLS_CLIENT_HELLO
Definition tls.h:68
#define TLS_SERVER_NAME
Definition tls.h:132
#define TLS_SERVER_NAME_HOST_NAME
Definition tls.h:133
#define TLS_MAX_FRAGMENT_LENGTH
Definition tls.h:136
#define TLS_NAMED_GROUP
Definition tls.h:143
#define TLS_SESSION_TICKET
Definition tls.h:158
#define TLS_SIGNATURE_ALGORITHMS
Definition tls.h:152

References __attribute__, assert, tls_connection::client, tls_verify_data::client, code, tls_cipher_suite::code, tls_signature_hash_algorithm::code, cpu_to_le32, data, for_each_table_entry, group, hello, htonl, htons, len, tls_session::list, max, memcpy(), memset(), name, tls_session::name, random(), tls_client::random, tls_connection::secure_renegotiation, tls_connection::session, tls_connection::session_id, tls_connection::session_id_len, strlen(), tls_session::ticket, tls_session::ticket_len, TLS_CIPHER_SUITES, TLS_CLIENT_HELLO, TLS_EXTENDED_MASTER_SECRET, TLS_MAX_FRAGMENT_LENGTH, TLS_MAX_FRAGMENT_LENGTH_VALUE, TLS_NAMED_GROUP, TLS_NAMED_GROUPS, TLS_NUM_CIPHER_SUITES, TLS_NUM_NAMED_GROUPS, TLS_NUM_SIG_HASH_ALGORITHMS, TLS_RENEGOTIATION_INFO, TLS_SERVER_NAME, TLS_SERVER_NAME_HOST_NAME, TLS_SESSION_TICKET, TLS_SIG_HASH_ALGORITHMS, TLS_SIGNATURE_ALGORITHMS, TLS_VERSION_MAX, type, typeof(), tls_connection::verify, and version.

Referenced by tls_new_server_hello(), and tls_send_client_hello().

◆ 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 2160 of file tls.c.

2160 {
2161
2162 return tls_client_hello ( tls, tls_send_handshake );
2163}
static int tls_client_hello(struct tls_connection *tls, int(*action)(struct tls_connection *tls, const void *data, size_t len))
Digest or transmit Client Hello record.
Definition tls.c:1977

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 2171 of file tls.c.

2171 {
2172 struct {
2174 uint8_t data[0];
2175 } __attribute__ (( packed )) *certificate;
2176 struct {
2177 uint32_t type_length;
2179 typeof ( *certificate ) certificates[0];
2180 } __attribute__ (( packed )) *certificates;
2181 struct x509_link *link;
2182 struct x509_certificate *cert;
2183 struct io_buffer *iobuf;
2184 size_t len;
2185
2186 /* Calculate length of client certificates */
2187 len = 0;
2189 cert = link->cert;
2190 len += ( sizeof ( *certificate ) + cert->raw.len );
2191 DBGC ( tls, "TLS %p sending client certificate %s\n",
2192 tls, x509_name ( cert ) );
2193 }
2194
2195 /* Allocate storage for Certificate record (which may be too
2196 * large for the stack).
2197 */
2198 iobuf = tls_alloc_iob ( tls, ( sizeof ( *certificates ) + len ) );
2199 if ( ! iobuf )
2200 return -ENOMEM_CERTIFICATE;
2201
2202 /* Populate record */
2203 certificates = iob_put ( iobuf, sizeof ( *certificates ) );
2204 certificates->type_length =
2206 htonl ( sizeof ( *certificates ) + len -
2207 sizeof ( certificates->type_length ) ) );
2208 tls_set_uint24 ( &certificates->length, len );
2210 cert = link->cert;
2211 certificate = iob_put ( iobuf, sizeof ( *certificate ) );
2212 tls_set_uint24 ( &certificate->length, cert->raw.len );
2213 memcpy ( iob_put ( iobuf, cert->raw.len ), cert->raw.data,
2214 cert->raw.len );
2215 }
2216
2217 /* Transmit record */
2218 return tls_send_record ( tls, TLS_TYPE_HANDSHAKE,
2219 iob_disown ( iobuf ) );
2220}
u32 link
Link to next descriptor.
Definition ar9003_mac.h:1
u16 length
Definition sky2.h:1
const void * data
Start of data.
Definition asn1.h:23
size_t len
Length of data.
Definition asn1.h:25
A TLS 24-bit integer.
Definition tls.c:236
struct asn1_cursor raw
Raw certificate.
Definition x509.h:231
struct list_head links
List of links.
Definition x509.h:205
#define ENOMEM_CERTIFICATE
Definition tls.c:127
static void tls_set_uint24(tls24_t *field24, unsigned long value)
Set 24-bit field value.
Definition tls.c:262
#define TLS_CERTIFICATE
Definition tls.h:71

References __attribute__, tls_client::chain, tls_connection::client, cpu_to_le32, asn1_cursor::data, data, DBGC, ENOMEM_CERTIFICATE, htonl, iob_disown, iob_put, asn1_cursor::len, len, length, link, x509_chain::links, io_buffer::list, list_for_each_entry, memcpy(), x509_certificate::raw, tls_alloc_iob(), TLS_CERTIFICATE, tls_send_record(), tls_set_uint24(), TLS_TYPE_HANDSHAKE, typeof(), 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 2228 of file tls.c.

2228 {
2229 struct tls_cipherspec *cipherspec = &tls->tx.cipherspec.pending;
2230 struct tls_cipher_suite *suite = cipherspec->suite;
2231 int rc;
2232
2233 /* Transmit Client Key Exchange record via key exchange algorithm */
2234 if ( ( rc = suite->exchange->client ( tls ) ) != 0 ) {
2235 DBGC ( tls, "TLS %p could not exchange keys: %s\n",
2236 tls, strerror ( rc ) );
2237 return rc;
2238 }
2239
2240 /* Generate master secret */
2242
2243 /* Generate keys from master secret */
2244 if ( ( rc = tls_generate_keys ( tls ) ) != 0 ) {
2245 DBGC ( tls, "TLS %p could not generate keys: %s\n",
2246 tls, strerror ( rc ) );
2247 return rc;
2248 }
2249
2250 return 0;
2251}
int(* client)(struct tls_connection *tls)
Transmit Client Key Exchange record.
Definition tls.h:215
static void tls_generate_master_secret(struct tls_connection *tls)
Generate master secret.
Definition tls.c:927
static int tls_generate_keys(struct tls_connection *tls)
Generate key material.
Definition tls.c:978

References tls_tx::cipherspec, tls_key_exchange_algorithm::client, DBGC, tls_cipher_suite::exchange, tls_cipherspec_pair::pending, rc, strerror(), tls_cipherspec::suite, tls_generate_keys(), tls_generate_master_secret(), and tls_connection::tx.

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 2259 of file tls.c.

2259 {
2260 struct digest_algorithm *digest = tls->key.digest;
2261 struct x509_certificate *cert = x509_first ( tls->client.chain );
2262 struct pubkey_algorithm *pubkey = cert->signature_algorithm->pubkey;
2263 struct asn1_cursor *key = privkey_cursor ( tls->client.key );
2264 uint8_t digest_out[ digest->digestsize ];
2265 struct tls_signature_hash_algorithm *sig_hash = NULL;
2266 struct asn1_builder builder = { NULL, 0 };
2267 int rc;
2268
2269 /* Generate digest to be signed */
2270 tls_verify_handshake ( tls, digest_out );
2271
2272 /* TLSv1.2 and later use explicit algorithm identifiers */
2273 if ( tls_version ( tls, TLS_VERSION_TLS_1_2 ) ) {
2274 sig_hash = tls_signature_hash_algorithm ( pubkey, digest );
2275 if ( ! sig_hash ) {
2276 DBGC ( tls, "TLS %p could not identify (%s,%s) "
2277 "signature and hash algorithm\n", tls,
2278 pubkey->name, digest->name );
2280 goto err_sig_hash;
2281 }
2282 }
2283
2284 /* Sign digest */
2285 if ( ( rc = pubkey_sign ( pubkey, key, digest, digest_out,
2286 &builder ) ) != 0 ) {
2287 DBGC ( tls, "TLS %p could not sign %s digest using %s client "
2288 "private key: %s\n", tls, digest->name, pubkey->name,
2289 strerror ( rc ) );
2290 goto err_pubkey_sign;
2291 }
2292
2293 /* Construct Certificate Verify record */
2294 {
2295 int use_sig_hash = ( ( sig_hash == NULL ) ? 0 : 1 );
2296 struct {
2297 uint32_t type_length;
2298 uint16_t sig_hash[use_sig_hash];
2299 uint16_t signature_len;
2300 } __attribute__ (( packed )) header;
2301
2302 header.type_length = ( cpu_to_le32 ( TLS_CERTIFICATE_VERIFY ) |
2303 htonl ( builder.len +
2304 sizeof ( header ) -
2305 sizeof ( header.type_length )));
2306 if ( use_sig_hash ) {
2307 memcpy ( &header.sig_hash[0], &sig_hash->code,
2308 sizeof ( header.sig_hash[0] ) );
2309 }
2310 header.signature_len = htons ( builder.len );
2311
2312 if ( ( rc = asn1_prepend_raw ( &builder, &header,
2313 sizeof ( header ) ) ) != 0 ) {
2314 DBGC ( tls, "TLS %p could not construct Certificate "
2315 "Verify: %s\n", tls, strerror ( rc ) );
2316 goto err_prepend;
2317 }
2318 }
2319
2320 /* Transmit record */
2321 if ( ( rc = tls_send_handshake ( tls, builder.data,
2322 builder.len ) ) != 0 ) {
2323 goto err_send;
2324 }
2325
2326 err_send:
2327 err_prepend:
2328 err_pubkey_sign:
2329 err_sig_hash:
2330 zfree ( builder.data );
2331 return rc;
2332}
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
struct pubkey_algorithm * pubkey
Public-key algorithm (if applicable).
Definition asn1.h:420
struct asn1_algorithm * signature_algorithm
Signature algorithm.
Definition x509.h:239
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:1356
#define TLS_CERTIFICATE_VERIFY
Definition tls.h:75

References __attribute__, asn1_prepend_raw(), tls_client::chain, tls_connection::client, tls_signature_hash_algorithm::code, cpu_to_le32, asn1_builder::data, DBGC, tls_key_schedule::digest, digest_algorithm::digestsize, ENOTSUP_SIG_HASH, header, htonl, htons, key, tls_client::key, tls_connection::key, asn1_builder::len, memcpy(), digest_algorithm::name, pubkey_algorithm::name, NULL, privkey_cursor(), asn1_algorithm::pubkey, pubkey_sign(), rc, x509_certificate::signature_algorithm, strerror(), TLS_CERTIFICATE_VERIFY, tls_send_handshake(), tls_signature_hash_algorithm(), tls_verify_handshake(), tls_version(), TLS_VERSION_TLS_1_2, 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 2340 of file tls.c.

2340 {
2341 static const struct {
2342 uint8_t spec;
2343 } __attribute__ (( packed )) change_cipher = {
2344 .spec = TLS_CHANGE_CIPHER_SPEC,
2345 };
2346
2348 &change_cipher, sizeof ( change_cipher ) );
2349}
uint16_t spec
ENA specification version.
Definition ena.h:15
#define TLS_CHANGE_CIPHER_SPEC
Change cipher spec magic byte.
Definition tls.h:55
#define TLS_TYPE_CHANGE_CIPHER
Change cipher content type.
Definition tls.h:52

References __attribute__, spec, TLS_CHANGE_CIPHER_SPEC, tls_send_plaintext(), and TLS_TYPE_CHANGE_CIPHER.

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 2357 of file tls.c.

2357 {
2358 struct digest_algorithm *digest = tls->key.digest;
2359 struct tls_key_schedule *key = &tls->key;
2360 struct {
2361 uint32_t type_length;
2362 uint8_t verify_data[ sizeof ( tls->verify.client ) ];
2363 } __attribute__ (( packed )) finished;
2364 uint8_t digest_out[ digest->digestsize ];
2365 int rc;
2366
2367 /* Fail unless bound identity has been validated */
2368 if ( ! ( key->bound &&
2369 x509_is_valid ( key->bound, tls->server.root ) ) ) {
2370 DBGC ( tls, "TLS %p bound identity is not valid\n", tls );
2371 return -EPERM_BOUND;
2372 }
2373
2374 /* Construct client verification data */
2375 tls_verify_handshake ( tls, digest_out );
2376 tls_prf_label ( tls, tls->verify.client, sizeof ( tls->verify.client ),
2377 "client finished", digest_out, sizeof ( digest_out ) );
2378
2379 /* Construct record */
2380 memset ( &finished, 0, sizeof ( finished ) );
2381 finished.type_length = ( cpu_to_le32 ( TLS_FINISHED ) |
2382 htonl ( sizeof ( finished ) -
2383 sizeof ( finished.type_length ) ) );
2384 memcpy ( finished.verify_data, tls->verify.client,
2385 sizeof ( finished.verify_data ) );
2386
2387 /* Transmit record */
2388 if ( ( rc = tls_send_handshake ( tls, &finished,
2389 sizeof ( finished ) ) ) != 0 )
2390 return rc;
2391
2392 /* Mark client as finished */
2393 pending_put ( &tls->client.negotiation );
2394
2395 return 0;
2396}
#define EPERM_BOUND
Definition tls.c:195
#define TLS_FINISHED
Definition tls.h:77

References __attribute__, tls_connection::client, tls_verify_data::client, cpu_to_le32, DBGC, tls_key_schedule::digest, digest_algorithm::digestsize, EPERM_BOUND, htonl, key, tls_connection::key, memcpy(), memset(), tls_client::negotiation, pending_put(), rc, tls_server::root, tls_connection::server, TLS_FINISHED, tls_prf_label, tls_send_handshake(), tls_verify_handshake(), tls_connection::verify, and x509_is_valid().

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 2428 of file tls.c.

2429 {
2430 const struct {
2431 uint8_t spec;
2432 } __attribute__ (( packed )) *change_cipher = iobuf->data;
2433 size_t len = iob_len ( iobuf );
2434 int rc;
2435
2436 /* Sanity check */
2437 if ( ( sizeof ( *change_cipher ) != len ) ||
2438 ( change_cipher->spec != TLS_CHANGE_CIPHER_SPEC ) ) {
2439 DBGC ( tls, "TLS %p received invalid Change Cipher\n", tls );
2440 DBGC_HD ( tls, change_cipher, len );
2441 return -EINVAL_CHANGE_CIPHER;
2442 }
2443 iob_pull ( iobuf, sizeof ( *change_cipher ) );
2444
2445 /* Change receive cipher spec */
2446 if ( ( rc = tls_change_cipher ( tls, &tls->rx.cipherspec ) ) != 0 ) {
2447 DBGC ( tls, "TLS %p could not activate RX cipher: %s\n",
2448 tls, strerror ( rc ) );
2449 return rc;
2450 }
2451 tls->rx.seq = ~( ( uint64_t ) 0 );
2452
2453 return 0;
2454}
unsigned long long uint64_t
Definition stdint.h:13
#define iob_pull(iobuf, len)
Definition iobuf.h:107
uint64_t seq
Sequence number.
Definition tls.h:483
#define EINVAL_CHANGE_CIPHER
Definition tls.c:59
static int tls_change_cipher(struct tls_connection *tls, struct tls_cipherspec_pair *pair)
Activate next cipher suite.
Definition tls.c:1323

References __attribute__, tls_rx::cipherspec, io_buffer::data, DBGC, DBGC_HD, EINVAL_CHANGE_CIPHER, iob_len(), iob_pull, len, rc, tls_connection::rx, tls_rx::seq, spec, strerror(), tls_change_cipher(), and TLS_CHANGE_CIPHER_SPEC.

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 2463 of file tls.c.

2464 {
2465 const struct {
2466 uint8_t level;
2467 uint8_t description;
2468 char next[0];
2469 } __attribute__ (( packed )) *alert = iobuf->data;
2470 size_t len = iob_len ( iobuf );
2471
2472 /* Sanity check */
2473 if ( sizeof ( *alert ) != len ) {
2474 DBGC ( tls, "TLS %p received overlength Alert\n", tls );
2475 DBGC_HD ( tls, alert, len );
2476 return -EINVAL_ALERT;
2477 }
2478 iob_pull ( iobuf, sizeof ( *alert ) );
2479
2480 /* Handle alert */
2481 switch ( alert->level ) {
2482 case TLS_ALERT_WARNING:
2483 switch ( alert->description ) {
2485 DBGC ( tls, "TLS %p closed by notification\n", tls );
2486 tls_close ( tls, 0 );
2487 break;
2488 default:
2489 DBGC ( tls, "TLS %p received warning alert %d\n",
2490 tls, alert->description );
2491 break;
2492 }
2493 return 0;
2494 case TLS_ALERT_FATAL:
2495 DBGC ( tls, "TLS %p received fatal alert %d\n",
2496 tls, alert->description );
2497 return -EPERM_ALERT;
2498 default:
2499 DBGC ( tls, "TLS %p received unknown alert level %d"
2500 "(alert %d)\n", tls, alert->level, alert->description );
2501 return -EIO_ALERT;
2502 }
2503}
uint32_t next
Next descriptor address.
Definition dwmac.h:11
#define EINVAL_ALERT
Definition tls.c:63
#define EPERM_ALERT
Definition tls.c:171
#define EIO_ALERT
Definition tls.c:115
#define TLS_ALERT_FATAL
Definition tls.h:81

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 void *data __unused,
size_t len __unused )
static

Receive new Hello Request handshake record.

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

Definition at line 2513 of file tls.c.

2515 {
2516
2517 /* Ignore if a handshake is in progress */
2518 if ( ! tls_ready ( tls ) ) {
2519 DBGC ( tls, "TLS %p ignoring Hello Request\n", tls );
2520 return 0;
2521 }
2522
2523 /* Fail unless server supports secure renegotiation */
2524 if ( ! ( tls->secure_renegotiation && tls->extended_master_secret ) ) {
2525 DBGC ( tls, "TLS %p refusing to renegotiate insecurely\n",
2526 tls );
2527 return -EPERM_RENEG_INSECURE;
2528 }
2529
2530 /* Restart negotiation */
2531 tls_restart ( tls );
2532
2533 return 0;
2534}
static int tls_ready(struct tls_connection *tls)
Determine if TLS connection is ready for application data.
Definition tls.c:274
static void tls_restart(struct tls_connection *tls)
Restart negotiation.
Definition tls.c:1937
#define EPERM_RENEG_INSECURE
Definition tls.c:179

References __unused, data, DBGC, EPERM_RENEG_INSECURE, tls_connection::extended_master_secret, len, tls_connection::secure_renegotiation, tls_ready(), and tls_restart().

Referenced by tls_new_handshake().

◆ tls_new_server_hello()

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

Receive new Server Hello handshake record.

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

Definition at line 2544 of file tls.c.

2545 {
2546 const struct {
2548 uint8_t random[32];
2549 uint8_t session_id_len;
2550 uint8_t session_id[0];
2551 } __attribute__ (( packed )) *hello_a = data;
2552 const uint8_t *session_id;
2553 const struct {
2554 uint16_t cipher_suite;
2555 uint8_t compression_method;
2556 char next[0];
2557 } __attribute__ (( packed )) *hello_b;
2558 const struct {
2559 uint16_t len;
2560 uint8_t data[0];
2561 } __attribute__ (( packed )) *exts;
2562 const struct {
2563 uint16_t type;
2564 uint16_t len;
2565 uint8_t data[0];
2566 } __attribute__ (( packed )) *ext;
2567 const struct {
2568 uint8_t len;
2569 uint8_t data[0];
2570 } __attribute__ (( packed )) *reneg = NULL;
2571 const struct {
2572 uint8_t data[0];
2573 } __attribute__ (( packed )) *ems = NULL;
2575 size_t exts_len;
2576 size_t ext_len;
2577 size_t remaining;
2578 int rc;
2579
2580 /* Parse header */
2581 if ( ( sizeof ( *hello_a ) > len ) ||
2582 ( hello_a->session_id_len > ( len - sizeof ( *hello_a ) ) ) ||
2583 ( sizeof ( *hello_b ) > ( len - sizeof ( *hello_a ) -
2584 hello_a->session_id_len ) ) ) {
2585 DBGC ( tls, "TLS %p received underlength Server Hello\n", tls );
2586 DBGC_HD ( tls, data, len );
2587 return -EINVAL_HELLO;
2588 }
2589 session_id = hello_a->session_id;
2590 hello_b = ( ( void * ) ( session_id + hello_a->session_id_len ) );
2591
2592 /* Parse extensions, if present */
2593 remaining = ( len - sizeof ( *hello_a ) - hello_a->session_id_len -
2594 sizeof ( *hello_b ) );
2595 if ( remaining ) {
2596
2597 /* Parse extensions length */
2598 exts = ( ( void * ) hello_b->next );
2599 if ( ( sizeof ( *exts ) > remaining ) ||
2600 ( ( exts_len = ntohs ( exts->len ) ) >
2601 ( remaining - sizeof ( *exts ) ) ) ) {
2602 DBGC ( tls, "TLS %p received underlength extensions\n",
2603 tls );
2604 DBGC_HD ( tls, data, len );
2605 return -EINVAL_HELLO;
2606 }
2607
2608 /* Parse extensions */
2609 for ( ext = ( ( void * ) exts->data ), remaining = exts_len ;
2610 remaining ;
2611 ext = ( ( ( void * ) ext ) + sizeof ( *ext ) + ext_len ),
2612 remaining -= ( sizeof ( *ext ) + ext_len ) ) {
2613
2614 /* Parse extension length */
2615 if ( ( sizeof ( *ext ) > remaining ) ||
2616 ( ( ext_len = ntohs ( ext->len ) ) >
2617 ( remaining - sizeof ( *ext ) ) ) ) {
2618 DBGC ( tls, "TLS %p received underlength "
2619 "extension\n", tls );
2620 DBGC_HD ( tls, data, len );
2621 return -EINVAL_HELLO;
2622 }
2623
2624 /* Record known extensions */
2625 switch ( ext->type ) {
2626 case htons ( TLS_RENEGOTIATION_INFO ) :
2627 reneg = ( ( void * ) ext->data );
2628 if ( ( sizeof ( *reneg ) > ext_len ) ||
2629 ( reneg->len >
2630 ( ext_len - sizeof ( *reneg ) ) ) ) {
2631 DBGC ( tls, "TLS %p received "
2632 "underlength renegotiation "
2633 "info\n", tls );
2634 DBGC_HD ( tls, data, len );
2635 return -EINVAL_HELLO;
2636 }
2637 break;
2639 ems = ( ( void * ) ext->data );
2640 break;
2641 }
2642 }
2643 }
2644
2645 /* Check and store protocol version */
2646 version = ntohs ( hello_a->version );
2647 if ( version < TLS_VERSION_MIN ) {
2648 DBGC ( tls, "TLS %p does not support protocol version %d.%d\n",
2649 tls, ( version >> 8 ), ( version & 0xff ) );
2650 return -ENOTSUP_VERSION;
2651 }
2652 if ( version > tls->version ) {
2653 DBGC ( tls, "TLS %p server attempted to illegally upgrade to "
2654 "protocol version %d.%d\n",
2655 tls, ( version >> 8 ), ( version & 0xff ) );
2656 return -EPROTO_VERSION;
2657 }
2658 tls->version = version;
2659 DBGC ( tls, "TLS %p using protocol version %d.%d\n",
2660 tls, ( version >> 8 ), ( version & 0xff ) );
2661
2662 /* Select cipher suite */
2663 if ( ( rc = tls_select_cipher ( tls, hello_b->cipher_suite ) ) != 0 )
2664 return rc;
2665
2666 /* Add preceding Client Hello to handshake digest */
2667 if ( ( rc = tls_client_hello ( tls, tls_add_handshake ) ) != 0 )
2668 return rc;
2669
2670 /* Copy out server random bytes */
2671 memcpy ( &tls->server.random, &hello_a->random,
2672 sizeof ( tls->server.random ) );
2673
2674 /* Handle extended master secret */
2675 tls->extended_master_secret = ( !! ems );
2676
2677 /* Check session ID */
2678 if ( hello_a->session_id_len &&
2679 ( hello_a->session_id_len == tls->session_id_len ) &&
2680 ( memcmp ( session_id, tls->session_id,
2681 tls->session_id_len ) == 0 ) ) {
2682
2683 /* Session ID match: reuse master secret */
2684 DBGC ( tls, "TLS %p resuming session ID:\n", tls );
2685 DBGC_HDA ( tls, 0, tls->session_id, tls->session_id_len );
2686 tls_resume_secret ( tls );
2687 if ( ( rc = tls_generate_keys ( tls ) ) != 0 )
2688 return rc;
2689
2690 /* Ensure master secret generation method matches */
2691 if ( tls->extended_master_secret !=
2693 DBGC ( tls, "TLS %p mismatched extended master secret "
2694 "extension\n", tls );
2695 return -EPERM_EMS;
2696 }
2697
2698 } else {
2699
2700 /* Record new session ID, if present */
2701 if ( hello_a->session_id_len &&
2702 ( hello_a->session_id_len <= sizeof ( tls->session_id ))){
2703 tls->session_id_len = hello_a->session_id_len;
2704 memcpy ( tls->session_id, session_id,
2705 tls->session_id_len );
2706 DBGC ( tls, "TLS %p new session ID:\n", tls );
2707 DBGC_HDA ( tls, 0, tls->session_id,
2708 tls->session_id_len );
2709 }
2710 }
2711
2712 /* Handle secure renegotiation */
2713 if ( tls->secure_renegotiation ) {
2714
2715 /* Secure renegotiation is expected; verify data */
2716 if ( ( reneg == NULL ) ||
2717 ( reneg->len != sizeof ( tls->verify ) ) ||
2718 ( memcmp ( reneg->data, &tls->verify,
2719 sizeof ( tls->verify ) ) != 0 ) ) {
2720 DBGC ( tls, "TLS %p server failed secure "
2721 "renegotiation\n", tls );
2722 return -EPERM_RENEG_VERIFY;
2723 }
2724
2725 } else if ( reneg != NULL ) {
2726
2727 /* Secure renegotiation is being enabled */
2728 if ( reneg->len != 0 ) {
2729 DBGC ( tls, "TLS %p server provided non-empty initial "
2730 "renegotiation\n", tls );
2731 return -EPERM_RENEG_VERIFY;
2732 }
2733 tls->secure_renegotiation = 1;
2734 }
2735
2736 return 0;
2737}
uint16_t ext
Extended status.
Definition ena.h:9
#define ENOTSUP_VERSION
Definition stp.c:46
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition string.c:115
int extended_master_secret
Extended master secret flag.
Definition tls.h:360
#define EPERM_EMS
Definition tls.c:191
static void tls_resume_secret(struct tls_connection *tls)
Resume from resumption master secret.
Definition tls.c:1119
#define EINVAL_HELLO
Definition tls.c:67
static int tls_select_cipher(struct tls_connection *tls, unsigned int cipher_suite)
Select next cipher suite.
Definition tls.c:1280
#define EPROTO_VERSION
Definition tls.c:199
#define EPERM_RENEG_VERIFY
Definition tls.c:183

References __attribute__, data, DBGC, DBGC_HD, DBGC_HDA, EINVAL_HELLO, ENOTSUP_VERSION, EPERM_EMS, EPERM_RENEG_VERIFY, EPROTO_VERSION, ext, tls_connection::extended_master_secret, tls_session::extended_master_secret, htons, len, memcmp(), memcpy(), next, ntohs, NULL, random(), tls_server::random, rc, tls_connection::secure_renegotiation, tls_connection::server, tls_connection::session, tls_connection::session_id, tls_connection::session_id_len, tls_add_handshake(), tls_client_hello(), TLS_EXTENDED_MASTER_SECRET, tls_generate_keys(), TLS_RENEGOTIATION_INFO, tls_resume_secret(), tls_select_cipher(), TLS_VERSION_MIN, type, tls_connection::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 void * data,
size_t len )
static

Receive New Session Ticket handshake record.

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

Definition at line 2747 of file tls.c.

2748 {
2749 const struct {
2751 uint16_t len;
2752 uint8_t ticket[0];
2753 } __attribute__ (( packed )) *new_session_ticket = data;
2754 size_t ticket_len;
2755
2756 /* Parse header */
2757 if ( sizeof ( *new_session_ticket ) > len ) {
2758 DBGC ( tls, "TLS %p received underlength New Session Ticket\n",
2759 tls );
2760 DBGC_HD ( tls, data, len );
2761 return -EINVAL_TICKET;
2762 }
2763 ticket_len = ntohs ( new_session_ticket->len );
2764 if ( ticket_len > ( len - sizeof ( *new_session_ticket ) ) ) {
2765 DBGC ( tls, "TLS %p received overlength New Session Ticket\n",
2766 tls );
2767 DBGC_HD ( tls, data, len );
2768 return -EINVAL_TICKET;
2769 }
2770
2771 /* Free any unapplied new session ticket */
2772 zfree ( tls->new_session_ticket );
2773 tls->new_session_ticket = NULL;
2774 tls->new_session_ticket_len = 0;
2775
2776 /* Record ticket */
2777 tls->new_session_ticket = malloc ( ticket_len );
2778 if ( ! tls->new_session_ticket )
2779 return -ENOMEM;
2780 memcpy ( tls->new_session_ticket, new_session_ticket->ticket,
2781 ticket_len );
2782 tls->new_session_ticket_len = ticket_len;
2783 DBGC ( tls, "TLS %p new session ticket:\n", tls );
2784 DBGC_HDA ( tls, 0, tls->new_session_ticket,
2786
2787 return 0;
2788}
size_t new_session_ticket_len
Length of new session ticket.
Definition tls.h:540
#define EINVAL_TICKET
Definition tls.c:107
u32 lifetime
For Lifetime-type KDEs, the lifetime in seconds.
Definition wpa.h:27

References __attribute__, data, DBGC, DBGC_HD, DBGC_HDA, EINVAL_TICKET, ENOMEM, len, lifetime, malloc(), memcpy(), tls_connection::new_session_ticket, tls_connection::new_session_ticket_len, ntohs, NULL, and zfree().

Referenced by tls_new_handshake().

◆ tls_parse_chain()

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

Parse certificate chain.

Parameters
tlsTLS connection
dataCertificate chain
lenLength of certificate chain
Return values
rcReturn status code

Definition at line 2798 of file tls.c.

2799 {
2800 struct x509_certificate *cert;
2801 size_t remaining = len;
2802 int rc;
2803
2804 /* Free any existing certificate chain */
2805 x509_chain_put ( tls->server.chain );
2806 tls->server.chain = NULL;
2807
2808 /* Certificate has changed and so the key schedule is no
2809 * longer bound to the server identity.
2810 */
2811 tls->key.bound = 0;
2812
2813 /* Create certificate chain */
2814 tls->server.chain = x509_alloc_chain();
2815 if ( ! tls->server.chain ) {
2816 rc = -ENOMEM_CHAIN;
2817 goto err_alloc_chain;
2818 }
2819
2820 /* Add certificates to chain */
2821 while ( remaining ) {
2822 const struct {
2823 tls24_t length;
2824 uint8_t data[0];
2825 } __attribute__ (( packed )) *certificate = data;
2826 size_t certificate_len;
2827 size_t record_len;
2828
2829 /* Parse header */
2830 if ( sizeof ( *certificate ) > remaining ) {
2831 DBGC ( tls, "TLS %p underlength certificate:\n", tls );
2832 DBGC_HDA ( tls, 0, data, remaining );
2834 goto err_underlength;
2835 }
2836 certificate_len = tls_uint24 ( &certificate->length );
2837 if ( certificate_len > ( remaining - sizeof ( *certificate ) )){
2838 DBGC ( tls, "TLS %p overlength certificate:\n", tls );
2839 DBGC_HDA ( tls, 0, data, remaining );
2841 goto err_overlength;
2842 }
2843 record_len = ( sizeof ( *certificate ) + certificate_len );
2844
2845 /* Add certificate to chain */
2846 if ( ( rc = x509_append_raw ( tls->server.chain,
2847 certificate->data,
2848 certificate_len ) ) != 0 ) {
2849 DBGC ( tls, "TLS %p could not append certificate: %s\n",
2850 tls, strerror ( rc ) );
2851 DBGC_HDA ( tls, 0, data, remaining );
2852 goto err_parse;
2853 }
2854 cert = x509_last ( tls->server.chain );
2855 DBGC ( tls, "TLS %p found certificate %s\n",
2856 tls, x509_name ( cert ) );
2857
2858 /* Move to next certificate in list */
2859 data += record_len;
2860 remaining -= record_len;
2861 }
2862
2863 /* Identify server certificate */
2864 cert = x509_first ( tls->server.chain );
2865 if ( ! cert ) {
2866 DBGC ( tls, "TLS %p certificate chain is empty\n", tls );
2867 rc = -ENOENT_CERT;
2868 goto err_empty;
2869 }
2870
2871 /* Verify server name */
2872 if ( ( rc = x509_check_name ( cert, tls->session->name ) ) != 0 ) {
2873 DBGC ( tls, "TLS %p server certificate does not match %s: %s\n",
2874 tls, tls->session->name, strerror ( rc ) );
2875 goto err_name;
2876 }
2877
2878 return 0;
2879
2880 err_name:
2881 err_empty:
2882 err_parse:
2883 err_overlength:
2884 err_underlength:
2885 x509_chain_put ( tls->server.chain );
2886 tls->server.chain = NULL;
2887 err_alloc_chain:
2888 return rc;
2889}
#define ENOMEM_CHAIN
Definition tls.c:131
#define EINVAL_CERTIFICATE
Definition tls.c:71
static unsigned long tls_uint24(const tls24_t *field24)
Extract 24-bit field value.
Definition tls.c:251
int x509_check_name(struct x509_certificate *cert, const char *name)
Check X.509 certificate name.
Definition x509.c:1564
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
static struct x509_certificate * x509_last(struct x509_chain *chain)
Get last certificate in X.509 certificate chain.
Definition x509.h:325

References __attribute__, tls_key_schedule::bound, tls_server::chain, data, DBGC, DBGC_HDA, EINVAL_CERTIFICATE, ENOENT_CERT, ENOMEM_CHAIN, tls_connection::key, len, length, tls_session::name, NULL, rc, tls_connection::server, tls_connection::session, strerror(), tls_uint24(), x509_alloc_chain(), x509_append_raw(), x509_chain_put(), x509_check_name(), x509_first(), x509_last(), and x509_name().

Referenced by tls_new_certificate().

◆ tls_new_certificate()

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

Receive new Certificate handshake record.

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

Definition at line 2899 of file tls.c.

2900 {
2901 const struct {
2903 uint8_t certificates[0];
2904 } __attribute__ (( packed )) *certificate = data;
2905 size_t certificates_len;
2906 int rc;
2907
2908 /* Parse header */
2909 if ( sizeof ( *certificate ) > len ) {
2910 DBGC ( tls, "TLS %p received underlength Server Certificate\n",
2911 tls );
2912 DBGC_HD ( tls, data, len );
2913 return -EINVAL_CERTIFICATES;
2914 }
2915 certificates_len = tls_uint24 ( &certificate->length );
2916 if ( certificates_len > ( len - sizeof ( *certificate ) ) ) {
2917 DBGC ( tls, "TLS %p received overlength Server Certificate\n",
2918 tls );
2919 DBGC_HD ( tls, data, len );
2920 return -EINVAL_CERTIFICATES;
2921 }
2922
2923 /* Parse certificate chain */
2924 if ( ( rc = tls_parse_chain ( tls, certificate->certificates,
2925 certificates_len ) ) != 0 )
2926 return rc;
2927
2928 return 0;
2929}
#define EINVAL_CERTIFICATES
Definition tls.c:75
static int tls_parse_chain(struct tls_connection *tls, const void *data, size_t len)
Parse certificate chain.
Definition tls.c:2798

References __attribute__, data, DBGC, DBGC_HD, EINVAL_CERTIFICATES, len, length, rc, tls_parse_chain(), and tls_uint24().

Referenced by tls_new_handshake().

◆ tls_new_server_key_exchange()

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

Receive new Server Key Exchange handshake record.

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

Definition at line 2939 of file tls.c.

2940 {
2941 struct tls_cipherspec *cipherspec = &tls->tx.cipherspec.pending;
2942 struct tls_cipher_suite *suite = cipherspec->suite;
2943 int rc;
2944
2945 /* Parse via key exchange algorithm */
2946 if ( ( rc = suite->exchange->server ( tls, data, len ) ) != 0 )
2947 return rc;
2948
2949 return 0;
2950}
int(* server)(struct tls_connection *tls, const void *data, size_t len)
Receive new Server Key Exchange record using ECDHE key exchange.
Definition tls.h:207

References tls_tx::cipherspec, data, tls_cipher_suite::exchange, len, tls_cipherspec_pair::pending, rc, tls_key_exchange_algorithm::server, tls_cipherspec::suite, and tls_connection::tx.

Referenced by tls_new_handshake().

◆ tls_new_certificate_request()

int tls_new_certificate_request ( struct tls_connection * tls,
const void *data __unused,
size_t len __unused )
static

Receive new Certificate Request handshake record.

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

Definition at line 2960 of file tls.c.

2962 {
2963 struct x509_certificate *cert;
2964 int rc;
2965
2966 /* We can only send a single certificate, so there is no point
2967 * in parsing the Certificate Request.
2968 */
2969
2970 /* Free any existing client certificate chain */
2971 x509_chain_put ( tls->client.chain );
2972 tls->client.chain = NULL;
2973
2974 /* Create client certificate chain */
2975 tls->client.chain = x509_alloc_chain();
2976 if ( ! tls->client.chain ) {
2977 rc = -ENOMEM;
2978 goto err_alloc;
2979 }
2980
2981 /* Determine client certificate to be sent, if any */
2982 cert = x509_find_key ( NULL, tls->client.key );
2983 if ( cert ) {
2984 DBGC ( tls, "TLS %p selected client certificate %s\n",
2985 tls, x509_name ( cert ) );
2986
2987 /* Append client certificate to chain */
2988 if ( ( rc = x509_append ( tls->client.chain, cert ) ) != 0 )
2989 goto err_append;
2990
2991 /* Append any relevant issuer certificates */
2992 if ( ( rc = x509_auto_append ( tls->client.chain,
2993 &certstore ) ) != 0 )
2994 goto err_auto_append;
2995 } else {
2996
2997 /* Send an empty certificate chain */
2998 DBGC ( tls, "TLS %p could not find certificate corresponding "
2999 "to private key\n", tls );
3000 }
3001
3002 return 0;
3003
3004 err_auto_append:
3005 err_append:
3006 x509_chain_put ( tls->client.chain );
3007 tls->client.chain = NULL;
3008 err_alloc:
3009 return rc;
3010}
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:1868
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:1835
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, data, DBGC, ENOMEM, tls_client::key, len, 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 void * data,
size_t len )
static

Receive new Server Hello Done handshake record.

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

Definition at line 3020 of file tls.c.

3021 {
3022 const struct {
3023 char next[0];
3024 } __attribute__ (( packed )) *hello_done = data;
3025 int rc;
3026
3027 /* Sanity check */
3028 if ( sizeof ( *hello_done ) != len ) {
3029 DBGC ( tls, "TLS %p received overlength Server Hello Done\n",
3030 tls );
3031 DBGC_HD ( tls, data, len );
3032 return -EINVAL_HELLO_DONE;
3033 }
3034
3035 /* Begin certificate validation */
3036 if ( ( rc = create_validator ( &tls->server.validator,
3037 tls->server.chain,
3038 tls->server.root ) ) != 0 ) {
3039 DBGC ( tls, "TLS %p could not start certificate validation: "
3040 "%s\n", tls, strerror ( rc ) );
3041 return rc;
3042 }
3043 pending_get ( &tls->server.validation );
3044
3045 return 0;
3046}
#define EINVAL_HELLO_DONE
Definition tls.c:79
int create_validator(struct interface *job, struct x509_chain *chain, struct x509_root *root)
Instantiate a certificate validator.
Definition validator.c:760

References __attribute__, tls_server::chain, create_validator(), data, DBGC, DBGC_HD, EINVAL_HELLO_DONE, len, next, pending_get(), rc, tls_server::root, tls_connection::server, strerror(), tls_server::validation, and tls_server::validator.

Referenced by tls_new_handshake().

◆ tls_new_finished()

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

Receive new Finished handshake record.

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

Definition at line 3056 of file tls.c.

3057 {
3058 struct tls_session *session = tls->session;
3059 struct tls_key_schedule *key = &tls->key;
3060 struct digest_algorithm *digest = tls->key.digest;
3061 const struct {
3062 uint8_t verify_data[ sizeof ( tls->verify.server ) ];
3063 char next[0];
3064 } __attribute__ (( packed )) *finished = data;
3065 uint8_t digest_out[ digest->digestsize ];
3066
3067 /* Sanity checks */
3068 if ( ! ( digest->digestsize && key->keyed && key->bound ) ) {
3069 DBGC ( tls, "TLS %p received premature Finished\n", tls );
3070 DBGC_HDA ( tls, 0, data, len );
3071 return -EINVAL_FINISHED;
3072 }
3073 if ( sizeof ( *finished ) != len ) {
3074 DBGC ( tls, "TLS %p received overlength Finished\n", tls );
3075 DBGC_HDA ( tls, 0, data, len );
3076 return -EINVAL_FINISHED;
3077 }
3078
3079 /* Verify data */
3080 tls_verify_handshake ( tls, digest_out );
3081 tls_prf_label ( tls, tls->verify.server, sizeof ( tls->verify.server ),
3082 "server finished", digest_out, sizeof ( digest_out ) );
3083 if ( memcmp ( tls->verify.server, finished->verify_data,
3084 sizeof ( tls->verify.server ) ) != 0 ) {
3085 DBGC ( tls, "TLS %p verification failed\n", tls );
3086 return -EPERM_VERIFY;
3087 }
3088
3089 /* Mark server as finished */
3090 pending_put ( &tls->server.negotiation );
3091
3092 /* If we are resuming a session (i.e. if the server Finished
3093 * arrives before the client Finished is sent), then schedule
3094 * transmission of Change Cipher and Finished.
3095 */
3096 if ( is_pending ( &tls->client.negotiation ) ) {
3098 tls_tx_resume ( tls );
3099 }
3100
3101 /* Record session ID, ticket, and master secret, if applicable */
3102 if ( x509_is_valid ( key->bound, tls->server.root ) &&
3103 ( tls->session_id_len || tls->new_session_ticket_len ) ) {
3106 x509_put ( session->cert );
3107 session->cert = x509_get ( key->bound );
3108 if ( tls->session_id_len ) {
3109 session->id_len = tls->session_id_len;
3110 memcpy ( session->id, tls->session_id,
3111 sizeof ( session->id ) );
3112 }
3113 if ( tls->new_session_ticket_len ) {
3114 zfree ( session->ticket );
3115 session->ticket = tls->new_session_ticket;
3116 session->ticket_len = tls->new_session_ticket_len;
3117 tls->new_session_ticket = NULL;
3118 tls->new_session_ticket_len = 0;
3119 }
3120 }
3121
3122 /* Move to end of session's connection list and allow other
3123 * connections to start making progress.
3124 */
3125 list_del ( &tls->list );
3126 list_add_tail ( &tls->list, &session->conn );
3127 tls_tx_resume_all ( session );
3128
3129 /* Send notification of a window change */
3131
3132 return 0;
3133}
#define list_add_tail(new, head)
Add a new entry to the tail of a list.
Definition list.h:94
uint8_t id[32]
Session ID.
Definition tls.h:348
size_t id_len
Length of session ID.
Definition tls.h:350
uint8_t server[12]
Server verification data.
Definition tls.h:176
#define EINVAL_FINISHED
Definition tls.c:83
static void tls_generate_resumption_master(struct tls_connection *tls)
Generate resumption master secret.
Definition tls.c:1059
#define EPERM_VERIFY
Definition tls.c:175
@ TLS_TX_FINISHED
Definition tls.h:192
@ TLS_TX_CHANGE_CIPHER
Definition tls.h:191
void xfer_window_changed(struct interface *intf)
Report change of flow control window.
Definition xfer.c:147

References __attribute__, tls_session::cert, tls_connection::client, tls_session::conn, data, DBGC, DBGC_HDA, tls_key_schedule::digest, digest_algorithm::digestsize, EINVAL_FINISHED, EPERM_VERIFY, tls_connection::extended_master_secret, tls_session::extended_master_secret, tls_session::id, tls_session::id_len, is_pending(), key, tls_connection::key, len, tls_connection::list, list_add_tail, list_del, memcmp(), memcpy(), tls_client::negotiation, tls_server::negotiation, tls_connection::new_session_ticket, tls_connection::new_session_ticket_len, next, NULL, tls_tx::pending, pending_put(), tls_connection::plainstream, tls_server::root, tls_connection::server, tls_verify_data::server, tls_connection::session, tls_connection::session_id, tls_connection::session_id_len, tls_session::ticket, tls_session::ticket_len, tls_generate_resumption_master(), tls_prf_label, TLS_TX_CHANGE_CIPHER, TLS_TX_FINISHED, tls_tx_resume(), tls_tx_resume_all(), tls_verify_handshake(), tls_connection::tx, tls_connection::verify, x509_get(), x509_is_valid(), x509_put(), xfer_window_changed(), and zfree().

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

Definition at line 3142 of file tls.c.

3143 {
3144 size_t remaining;
3145 int rc;
3146
3147 while ( ( remaining = iob_len ( iobuf ) ) ) {
3148 const struct {
3149 uint8_t type;
3151 uint8_t payload[0];
3152 } __attribute__ (( packed )) *handshake = iobuf->data;
3153 const void *payload;
3154 size_t payload_len;
3155 size_t record_len;
3156
3157 /* Parse header */
3158 if ( sizeof ( *handshake ) > remaining ) {
3159 /* Leave remaining fragment unconsumed */
3160 break;
3161 }
3162 payload_len = tls_uint24 ( &handshake->length );
3163 if ( payload_len > ( remaining - sizeof ( *handshake ) ) ) {
3164 /* Leave remaining fragment unconsumed */
3165 break;
3166 }
3167 payload = &handshake->payload;
3168 record_len = ( sizeof ( *handshake ) + payload_len );
3169
3170 /* Handle payload */
3171 switch ( handshake->type ) {
3172 case TLS_HELLO_REQUEST:
3173 rc = tls_new_hello_request ( tls, payload,
3174 payload_len );
3175 break;
3176 case TLS_SERVER_HELLO:
3177 rc = tls_new_server_hello ( tls, payload, payload_len );
3178 break;
3180 rc = tls_new_session_ticket ( tls, payload,
3181 payload_len );
3182 break;
3183 case TLS_CERTIFICATE:
3184 rc = tls_new_certificate ( tls, payload, payload_len );
3185 break;
3187 rc = tls_new_server_key_exchange ( tls, payload,
3188 payload_len );
3189 break;
3191 rc = tls_new_certificate_request ( tls, payload,
3192 payload_len );
3193 break;
3195 rc = tls_new_server_hello_done ( tls, payload,
3196 payload_len );
3197 break;
3198 case TLS_FINISHED:
3199 rc = tls_new_finished ( tls, payload, payload_len );
3200 break;
3201 default:
3202 DBGC ( tls, "TLS %p ignoring handshake type %d\n",
3203 tls, handshake->type );
3204 rc = 0;
3205 break;
3206 }
3207
3208 /* Add to handshake digest (except for Hello Requests,
3209 * which are explicitly excluded).
3210 */
3211 if ( handshake->type != TLS_HELLO_REQUEST )
3212 tls_add_handshake ( tls, handshake, record_len );
3213
3214 /* Abort on failure */
3215 if ( rc != 0 )
3216 return rc;
3217
3218 /* Move to next handshake record */
3219 iob_pull ( iobuf, record_len );
3220 }
3221
3222 return 0;
3223}
static int tls_new_finished(struct tls_connection *tls, const void *data, size_t len)
Receive new Finished handshake record.
Definition tls.c:3056
static int tls_new_server_hello(struct tls_connection *tls, const void *data, size_t len)
Receive new Server Hello handshake record.
Definition tls.c:2544
static int tls_new_certificate_request(struct tls_connection *tls, const void *data __unused, size_t len __unused)
Receive new Certificate Request handshake record.
Definition tls.c:2960
static int tls_new_session_ticket(struct tls_connection *tls, const void *data, size_t len)
Receive New Session Ticket handshake record.
Definition tls.c:2747
static int tls_new_hello_request(struct tls_connection *tls, const void *data __unused, size_t len __unused)
Receive new Hello Request handshake record.
Definition tls.c:2513
static int tls_new_certificate(struct tls_connection *tls, const void *data, size_t len)
Receive new Certificate handshake record.
Definition tls.c:2899
static int tls_new_server_hello_done(struct tls_connection *tls, const void *data, size_t len)
Receive new Server Hello Done handshake record.
Definition tls.c:3020
static int tls_new_server_key_exchange(struct tls_connection *tls, const void *data, size_t len)
Receive new Server Key Exchange handshake record.
Definition tls.c:2939
#define TLS_SERVER_HELLO
Definition tls.h:69
#define TLS_SERVER_KEY_EXCHANGE
Definition tls.h:72
#define TLS_NEW_SESSION_TICKET
Definition tls.h:70
#define TLS_HELLO_REQUEST
Definition tls.h:67
#define TLS_CERTIFICATE_REQUEST
Definition tls.h:73
#define TLS_SERVER_HELLO_DONE
Definition tls.h:74

References __attribute__, io_buffer::data, DBGC, iob_len(), iob_pull, length, rc, tls_add_handshake(), TLS_CERTIFICATE, TLS_CERTIFICATE_REQUEST, TLS_FINISHED, TLS_HELLO_REQUEST, tls_new_certificate(), tls_new_certificate_request(), 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_new_session_ticket(), TLS_SERVER_HELLO, TLS_SERVER_HELLO_DONE, TLS_SERVER_KEY_EXCHANGE, tls_uint24(), and type.

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 3232 of file tls.c.

3233 {
3234
3235 /* RFC4346 says that we should just ignore unknown record types */
3236 iob_pull ( iobuf, iob_len ( iobuf ) );
3237 return 0;
3238}

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 3247 of file tls.c.

3248 {
3249 struct io_buffer *iobuf;
3250 int rc;
3251
3252 /* Fail unless we are ready to receive data */
3253 if ( ! tls_ready ( tls ) )
3254 return -ENOTCONN;
3255
3256 /* Deliver each I/O buffer in turn */
3257 while ( ( iobuf = list_first_entry ( rx_data, struct io_buffer,
3258 list ) ) ) {
3259 list_del ( &iobuf->list );
3260 if ( ( rc = xfer_deliver_iob ( &tls->plainstream,
3261 iobuf ) ) != 0 ) {
3262 DBGC ( tls, "TLS %p could not deliver data: "
3263 "%s\n", tls, strerror ( rc ) );
3264 return rc;
3265 }
3266 }
3267
3268 return 0;
3269}
#define ENOTCONN
The socket is not connected.
Definition errno.h:570
#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 3279 of file tls.c.

3280 {
3281 int ( * handler ) ( struct tls_connection *tls,
3282 struct io_buffer *iobuf );
3283 struct io_buffer *tmp = NULL;
3284 struct io_buffer **iobuf;
3285 int rc;
3286
3287 /* Deliver data records as-is to the plainstream interface */
3288 if ( type == TLS_TYPE_DATA )
3289 return tls_new_data ( tls, rx_data );
3290
3291 /* Determine handler and fragment buffer */
3292 iobuf = &tmp;
3293 switch ( type ) {
3295 handler = tls_new_change_cipher;
3296 break;
3297 case TLS_TYPE_ALERT:
3298 handler = tls_new_alert;
3299 break;
3300 case TLS_TYPE_HANDSHAKE:
3301 handler = tls_new_handshake;
3302 iobuf = &tls->rx.handshake;
3303 break;
3304 default:
3305 DBGC ( tls, "TLS %p unknown record type %d\n", tls, type );
3306 handler = tls_new_unknown;
3307 break;
3308 }
3309
3310 /* Merge into a single I/O buffer */
3311 if ( *iobuf )
3312 list_add ( &(*iobuf)->list, rx_data );
3313 *iobuf = iob_concatenate ( rx_data );
3314 if ( ! *iobuf ) {
3315 DBGC ( tls, "TLS %p could not concatenate non-data record "
3316 "type %d\n", tls, type );
3318 goto err_concatenate;
3319 }
3320
3321 /* Handle record */
3322 if ( ( rc = handler ( tls, *iobuf ) ) != 0 )
3323 goto err_handle;
3324
3325 /* Discard I/O buffer if empty */
3326 if ( ! iob_len ( *iobuf ) ) {
3327 free_iob ( *iobuf );
3328 *iobuf = NULL;
3329 }
3330
3331 /* Sanity check */
3332 assert ( tmp == NULL );
3333
3334 return 0;
3335
3336 err_handle:
3337 free_iob ( *iobuf );
3338 *iobuf = NULL;
3339 err_concatenate:
3340 return rc;
3341}
struct io_buffer * iob_concatenate(struct list_head *list)
Concatenate I/O buffers into a single buffer.
Definition iobuf.c:250
#define list_add(new, head)
Add a new entry to the head of a list.
Definition list.h:70
static int tls_new_change_cipher(struct tls_connection *tls, struct io_buffer *iobuf)
Receive new Change Cipher record.
Definition tls.c:2428
#define ENOMEM_RX_CONCAT
Definition tls.c:147
static int tls_new_unknown(struct tls_connection *tls __unused, struct io_buffer *iobuf)
Receive new unknown record.
Definition tls.c:3232
static int tls_new_data(struct tls_connection *tls, struct list_head *rx_data)
Receive new data record.
Definition tls.c:3247
static int tls_new_handshake(struct tls_connection *tls, struct io_buffer *iobuf)
Receive new Handshake record.
Definition tls.c:3142
static int tls_new_alert(struct tls_connection *tls, struct io_buffer *iobuf)
Receive new Alert record.
Definition tls.c:2463
#define TLS_TYPE_DATA
Application data content type.
Definition tls.h:64

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 3357 of file tls.c.

3358 {
3359 struct tls_cipher_suite *suite = cipherspec->suite;
3360 struct digest_algorithm *digest = suite->digest;
3361
3362 hmac_init ( digest, ctx, cipherspec->mac_secret, suite->mac_len );
3363 hmac_update ( digest, ctx, authhdr, sizeof ( *authhdr ) );
3364}
void hmac_init(struct digest_algorithm *digest, void *ctx, const void *secret, size_t len)
Initialise HMAC.
Definition hmac.c:106

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 3374 of file tls.c.

3375 {
3376 struct digest_algorithm *digest = cipherspec->suite->digest;
3377
3378 hmac_update ( digest, ctx, data, len );
3379}

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 3388 of file tls.c.

3389 {
3390 struct digest_algorithm *digest = cipherspec->suite->digest;
3391
3392 hmac_final ( digest, ctx, hmac );
3393}

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 3404 of file tls.c.

3406 {
3407 struct digest_algorithm *digest = cipherspec->suite->digest;
3408 uint8_t ctx[ hmac_ctxsize ( digest ) ];
3409
3410 tls_hmac_init ( cipherspec, ctx, authhdr );
3411 tls_hmac_update ( cipherspec, ctx, data, len );
3412 tls_hmac_final ( cipherspec, ctx, hmac );
3413}
static void tls_hmac_init(struct tls_cipherspec *cipherspec, void *ctx, struct tls_auth_header *authhdr)
Initialise HMAC.
Definition tls.c:3357
static void tls_hmac_final(struct tls_cipherspec *cipherspec, void *ctx, void *hmac)
Finalise HMAC.
Definition tls.c:3388
static void tls_hmac_update(struct tls_cipherspec *cipherspec, void *ctx, const void *data, size_t len)
Update HMAC.
Definition tls.c:3374

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 3423 of file tls.c.

3425 {
3426 struct digest_algorithm *digest = cipherspec->suite->digest;
3427 uint8_t ctx[ hmac_ctxsize ( digest ) ];
3428 struct io_buffer *iobuf;
3429
3430 tls_hmac_init ( cipherspec, ctx, authhdr );
3431 list_for_each_entry ( iobuf, list, list ) {
3432 tls_hmac_update ( cipherspec, ctx, iobuf->data,
3433 iob_len ( iobuf ) );
3434 }
3435 tls_hmac_final ( cipherspec, ctx, hmac );
3436}

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 3445 of file tls.c.

3445 {
3446 struct tls_cipherspec *cipherspec = &tls->tx.cipherspec.active;
3447 struct tls_cipher_suite *suite = cipherspec->suite;
3448 struct cipher_algorithm *cipher = suite->cipher;
3449 struct tls_header *tlshdr;
3450 unsigned int count;
3451 size_t each;
3452
3453 /* Calculate number of records (allowing for zero-length records) */
3454 count = ( len ? ( ( len + TLS_TX_BUFSIZE - 1 ) / TLS_TX_BUFSIZE ) : 1 );
3455
3456 /* Calculate maximum additional length per record */
3457 each = ( sizeof ( *tlshdr ) + suite->record_iv_len + suite->mac_len +
3458 ( is_block_cipher ( cipher ) ? cipher->blocksize : 0 ) +
3459 cipher->authsize );
3460
3461 /* Calculate maximum total additional length */
3462 return ( count * each );
3463}
static unsigned int count
Number of entries.
Definition dwmac.h:220

References tls_cipherspec_pair::active, cipher_algorithm::authsize, cipher_algorithm::blocksize, tls_cipher_suite::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, 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 3672 of file tls.c.

3673 {
3674 uint8_t *padding;
3675 unsigned int pad;
3676 unsigned int i;
3677 size_t len;
3678
3679 /* Extract and verify padding */
3680 padding = ( iobuf->tail - 1 );
3681 pad = *padding;
3682 len = ( pad + 1 );
3683 if ( len > iob_len ( iobuf ) ) {
3684 DBGC ( tls, "TLS %p received underlength padding\n", tls );
3685 DBGC_HD ( tls, iobuf->data, iob_len ( iobuf ) );
3686 return -EINVAL_PADDING;
3687 }
3688 for ( i = 0 ; i < pad ; i++ ) {
3689 if ( *(--padding) != pad ) {
3690 DBGC ( tls, "TLS %p received bad padding\n", tls );
3691 DBGC_HD ( tls, iobuf->data, iob_len ( iobuf ) );
3692 return -EINVAL_PADDING;
3693 }
3694 }
3695
3696 return len;
3697}
u32 pad[9]
Padding.
Definition ar9003_mac.h:23
void * tail
End of data.
Definition iobuf.h:55
#define EINVAL_PADDING
Definition tls.c:95

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

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 3707 of file tls.c.

3709 {
3710 struct tls_cipherspec *cipherspec = &tls->rx.cipherspec.active;
3711 struct tls_cipher_suite *suite = cipherspec->suite;
3712 struct cipher_algorithm *cipher = suite->cipher;
3713 struct digest_algorithm *digest = suite->digest;
3714 size_t len = ntohs ( tlshdr->length );
3715 struct {
3716 uint8_t fixed[suite->fixed_iv_len];
3717 uint8_t record[suite->record_iv_len];
3718 } __attribute__ (( packed )) iv;
3719 struct tls_auth_header authhdr;
3720 uint8_t verify_mac[digest->digestsize];
3721 uint8_t verify_auth[cipher->authsize];
3722 struct io_buffer *first;
3723 struct io_buffer *last;
3724 struct io_buffer *iobuf;
3725 void *mac;
3726 void *auth;
3727 size_t check_len;
3728 int pad_len;
3729 int rc;
3730
3731 /* Locate first and last data buffers */
3732 assert ( ! list_empty ( rx_data ) );
3733 first = list_first_entry ( rx_data, struct io_buffer, list );
3734 last = list_last_entry ( rx_data, struct io_buffer, list );
3735
3736 /* Extract initialisation vector */
3737 if ( iob_len ( first ) < sizeof ( iv.record ) ) {
3738 DBGC ( tls, "TLS %p received underlength IV\n", tls );
3739 DBGC_HD ( tls, first->data, iob_len ( first ) );
3740 return -EINVAL_IV;
3741 }
3742 memcpy ( iv.fixed, cipherspec->fixed_iv, sizeof ( iv.fixed ) );
3743 memcpy ( iv.record, first->data, sizeof ( iv.record ) );
3744 iob_pull ( first, sizeof ( iv.record ) );
3745 len -= sizeof ( iv.record );
3746
3747 /* Extract unencrypted authentication tag */
3748 if ( iob_len ( last ) < cipher->authsize ) {
3749 DBGC ( tls, "TLS %p received underlength authentication tag\n",
3750 tls );
3751 DBGC_HD ( tls, last->data, iob_len ( last ) );
3752 return -EINVAL_MAC;
3753 }
3754 iob_unput ( last, cipher->authsize );
3755 len -= cipher->authsize;
3756 auth = last->tail;
3757
3758 /* Construct authentication data */
3759 authhdr.seq = cpu_to_be64 ( tls->rx.seq );
3760 authhdr.header.type = tlshdr->type;
3761 authhdr.header.version = tlshdr->version;
3762 authhdr.header.length = htons ( len );
3763
3764 /* Set initialisation vector */
3765 if ( ( rc = cipher_setiv ( cipher, cipherspec->cipher_ctx, &iv,
3766 sizeof ( iv ) ) ) != 0 ) {
3767 DBGC ( tls, "TLS %p could not set RX IV: %s\n",
3768 tls, strerror ( rc ) );
3769 return rc;
3770 }
3771
3772 /* Process authentication data, if applicable */
3773 if ( is_auth_cipher ( cipher ) ) {
3774 cipher_decrypt ( cipher, cipherspec->cipher_ctx, &authhdr,
3775 NULL, sizeof ( authhdr ) );
3776 }
3777
3778 /* Decrypt the received data */
3779 check_len = 0;
3780 list_for_each_entry ( iobuf, &tls->rx.data, list ) {
3781 cipher_decrypt ( cipher, cipherspec->cipher_ctx,
3782 iobuf->data, iobuf->data, iob_len ( iobuf ) );
3783 check_len += iob_len ( iobuf );
3784 }
3785 assert ( check_len == len );
3786
3787 /* Strip block padding, if applicable */
3788 if ( is_block_cipher ( cipher ) ) {
3789 pad_len = tls_verify_padding ( tls, last );
3790 if ( pad_len < 0 ) {
3791 /* Assume zero padding length to avoid timing attacks */
3792 pad_len = 0;
3793 }
3794 iob_unput ( last, pad_len );
3795 len -= pad_len;
3796 }
3797
3798 /* Extract decrypted MAC */
3799 if ( iob_len ( last ) < suite->mac_len ) {
3800 DBGC ( tls, "TLS %p received underlength MAC\n", tls );
3801 DBGC_HD ( tls, last->data, iob_len ( last ) );
3802 return -EINVAL_MAC;
3803 }
3804 iob_unput ( last, suite->mac_len );
3805 len -= suite->mac_len;
3806 mac = last->tail;
3807
3808 /* Dump received data */
3809 DBGC2 ( tls, "Received plaintext data:\n" );
3810 check_len = 0;
3811 list_for_each_entry ( iobuf, rx_data, list ) {
3812 DBGC2_HD ( tls, iobuf->data, iob_len ( iobuf ) );
3813 check_len += iob_len ( iobuf );
3814 }
3815 assert ( check_len == len );
3816
3817 /* Generate MAC */
3818 authhdr.header.length = htons ( len );
3819 if ( suite->mac_len )
3820 tls_hmac_list ( cipherspec, &authhdr, rx_data, verify_mac );
3821
3822 /* Generate authentication tag */
3823 cipher_auth ( cipher, cipherspec->cipher_ctx, verify_auth );
3824
3825 /* Verify MAC */
3826 if ( memcmp ( mac, verify_mac, suite->mac_len ) != 0 ) {
3827 DBGC ( tls, "TLS %p failed MAC verification\n", tls );
3828 return -EINVAL_MAC;
3829 }
3830
3831 /* Verify authentication tag */
3832 if ( memcmp ( auth, verify_auth, cipher->authsize ) != 0 ) {
3833 DBGC ( tls, "TLS %p failed authentication tag verification\n",
3834 tls );
3835 return -EINVAL_MAC;
3836 }
3837
3838 /* Process plaintext record */
3839 if ( ( rc = tls_new_record ( tls, tlshdr->type, rx_data ) ) != 0 )
3840 return rc;
3841
3842 return 0;
3843}
#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:91
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:3423
#define EINVAL_MAC
Definition tls.c:103
static int tls_verify_padding(struct tls_connection *tls, struct io_buffer *iobuf)
Verify block padding.
Definition tls.c:3672
static int tls_new_record(struct tls_connection *tls, unsigned int type, struct list_head *rx_data)
Receive new record.
Definition tls.c:3279

References __attribute__, tls_cipherspec_pair::active, assert, cipher_algorithm::authsize, tls_cipher_suite::cipher, cipher_auth(), tls_cipherspec::cipher_ctx, cipher_decrypt, cipher_setiv(), tls_rx::cipherspec, cpu_to_be64, io_buffer::data, tls_rx::data, DBGC, DBGC2, DBGC2_HD, DBGC_HD, tls_cipher_suite::digest, digest_algorithm::digestsize, EINVAL_IV, EINVAL_MAC, first, fixed, tls_cipherspec::fixed_iv, tls_cipher_suite::fixed_iv_len, 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(), ntohs, NULL, rc, tls_cipher_suite::record_iv_len, tls_connection::rx, tls_auth_header::seq, tls_rx::seq, strerror(), tls_cipherspec::suite, io_buffer::tail, tls_hmac_list(), tls_new_record(), tls_verify_padding(), tls_header::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 3858 of file tls.c.

3858 {
3859
3860 /* Block window unless we are ready to accept data */
3861 if ( ! tls_ready ( tls ) )
3862 return 0;
3863
3864 return xfer_window ( &tls->cipherstream );
3865}
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 3875 of file tls.c.

3877 {
3878 int rc;
3879
3880 /* Refuse unless we are ready to accept data */
3881 if ( ! tls_ready ( tls ) ) {
3882 rc = -ENOTCONN;
3883 goto done;
3884 }
3885
3886 /* Send data record */
3887 if ( ( rc = tls_send_record ( tls, TLS_TYPE_DATA,
3888 iob_disown ( iobuf ) ) ) != 0 )
3889 goto done;
3890
3891 done:
3892 free_iob ( iobuf );
3893 return rc;
3894}
struct bofm_section_header done
Definition bofm_test.c:46

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 3903 of file tls.c.

3904 {
3905
3906 /* Return cipherstream or validator progress as applicable */
3907 if ( is_pending ( &tls->server.validation ) ) {
3908 return job_progress ( &tls->server.validator, progress );
3909 } else {
3910 return job_progress ( &tls->cipherstream, progress );
3911 }
3912}
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 3943 of file tls.c.

3943 {
3944 struct tls_cipherspec *cipherspec = &tls->rx.cipherspec.active;
3945 struct cipher_algorithm *cipher = cipherspec->suite->cipher;
3946 size_t iv_len = cipherspec->suite->record_iv_len;
3947 size_t data_len = ntohs ( tls->rx.header.length );
3948 size_t remaining = data_len;
3949 size_t frag_len;
3950 size_t reserve;
3951 struct io_buffer *iobuf;
3952 struct io_buffer *tmp;
3953 int rc;
3954
3955 /* Sanity check */
3956 assert ( ( TLS_RX_BUFSIZE % cipher->alignsize ) == 0 );
3957
3958 /* Calculate alignment reservation at start of first data buffer */
3959 reserve = ( ( -iv_len ) & ( cipher->alignsize - 1 ) );
3960 remaining += reserve;
3961
3962 /* Allocate data buffers now that we know the length */
3963 assert ( list_empty ( &tls->rx.data ) );
3964 while ( remaining ) {
3965
3966 /* Calculate fragment length. Ensure that no block is
3967 * smaller than TLS_RX_MIN_BUFSIZE (by increasing the
3968 * allocation length if necessary).
3969 */
3970 frag_len = remaining;
3971 if ( frag_len > TLS_RX_BUFSIZE )
3972 frag_len = TLS_RX_BUFSIZE;
3973 remaining -= frag_len;
3974 if ( remaining < TLS_RX_MIN_BUFSIZE ) {
3975 frag_len += remaining;
3976 remaining = 0;
3977 }
3978
3979 /* Allocate buffer */
3980 iobuf = alloc_iob_raw ( frag_len, TLS_RX_ALIGN, 0 );
3981 if ( ! iobuf ) {
3982 DBGC ( tls, "TLS %p could not allocate %zd of %zd "
3983 "bytes for receive buffer\n", tls,
3984 remaining, data_len );
3985 rc = -ENOMEM_RX_DATA;
3986 goto err;
3987 }
3988
3989 /* Ensure tailroom is exactly what we asked for. This
3990 * will result in unaligned I/O buffers when the
3991 * fragment length is unaligned, which can happen only
3992 * before we switch to using a block cipher.
3993 */
3994 iob_reserve ( iobuf, ( iob_tailroom ( iobuf ) - frag_len ) );
3995
3996 /* Ensure first buffer length will be aligned to a
3997 * multiple of the cipher alignment size after
3998 * stripping the record IV.
3999 */
4000 iob_reserve ( iobuf, reserve );
4001 reserve = 0;
4002
4003 /* Add I/O buffer to list */
4004 list_add_tail ( &iobuf->list, &tls->rx.data );
4005 }
4006
4007 /* Move to data state */
4008 tls->rx.state = TLS_RX_DATA;
4009
4010 return 0;
4011
4012 err:
4013 list_for_each_entry_safe ( iobuf, tmp, &tls->rx.data, list ) {
4014 list_del ( &iobuf->list );
4015 free_iob ( iobuf );
4016 }
4017 return rc;
4018}
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:180
size_t alignsize
Alignment size.
Definition crypto.h:80
enum tls_rx_state state
State machine current state.
Definition tls.h:485
struct tls_header header
Current received record header.
Definition tls.h:487
#define ENOMEM_RX_DATA
Definition tls.c:143
#define TLS_RX_MIN_BUFSIZE
Minimum RX I/O buffer size.
Definition tls.h:595
#define TLS_RX_ALIGN
RX I/O buffer alignment.
Definition tls.h:598
@ TLS_RX_DATA
Definition tls.h:182
#define TLS_RX_BUFSIZE
RX I/O buffer size.
Definition tls.h:587
uint32_t data_len
Microcode data size (or 0 to indicate 2000 bytes).
Definition ucode.h:15

References tls_cipherspec_pair::active, cipher_algorithm::alignsize, alloc_iob_raw(), assert, tls_cipher_suite::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, 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 4026 of file tls.c.

4026 {
4027 struct io_buffer *iobuf;
4028 int rc;
4029
4030 /* Move current buffer to end of list */
4031 iobuf = list_first_entry ( &tls->rx.data, struct io_buffer, list );
4032 list_del ( &iobuf->list );
4033 list_add_tail ( &iobuf->list, &tls->rx.data );
4034
4035 /* Continue receiving data if any space remains */
4036 iobuf = list_first_entry ( &tls->rx.data, struct io_buffer, list );
4037 if ( iob_tailroom ( iobuf ) )
4038 return 0;
4039
4040 /* Process record */
4041 if ( ( rc = tls_new_ciphertext ( tls, &tls->rx.header,
4042 &tls->rx.data ) ) != 0 )
4043 return rc;
4044
4045 /* Increment RX sequence number */
4046 tls->rx.seq += 1;
4047
4048 /* Return to header state */
4049 assert ( list_empty ( &tls->rx.data ) );
4050 tls->rx.state = TLS_RX_HEADER;
4051 iob_unput ( &tls->rx.iobuf, sizeof ( tls->rx.header ) );
4052
4053 return 0;
4054}
struct io_buffer iobuf
Current received record header (static I/O buffer).
Definition tls.h:489
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:3707
@ TLS_RX_HEADER
Definition tls.h:181

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::seq, 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 4062 of file tls.c.

4062 {
4063
4064 /* Open window until we are ready to accept data */
4065 if ( ! tls_ready ( tls ) )
4066 return -1UL;
4067
4068 return xfer_window ( &tls->plainstream );
4069}

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 4079 of file tls.c.

4081 {
4082 size_t frag_len;
4083 int ( * process ) ( struct tls_connection *tls );
4084 struct io_buffer *dest;
4085 int rc;
4086
4087 while ( iob_len ( iobuf ) ) {
4088
4089 /* Select buffer according to current state */
4090 switch ( tls->rx.state ) {
4091 case TLS_RX_HEADER:
4092 dest = &tls->rx.iobuf;
4094 break;
4095 case TLS_RX_DATA:
4096 dest = list_first_entry ( &tls->rx.data,
4097 struct io_buffer, list );
4098 assert ( dest != NULL );
4100 break;
4101 default:
4102 assert ( 0 );
4104 goto done;
4105 }
4106
4107 /* Copy data portion to buffer */
4108 frag_len = iob_len ( iobuf );
4109 if ( frag_len > iob_tailroom ( dest ) )
4110 frag_len = iob_tailroom ( dest );
4111 memcpy ( iob_put ( dest, frag_len ), iobuf->data, frag_len );
4112 iob_pull ( iobuf, frag_len );
4113
4114 /* Process data if buffer is now full */
4115 if ( iob_tailroom ( dest ) == 0 ) {
4116 if ( ( rc = process ( tls ) ) != 0 ) {
4117 tls_close_alert ( tls, rc );
4118 goto done;
4119 }
4120 }
4121 }
4122 rc = 0;
4123
4124 done:
4125 free_iob ( iobuf );
4126 return rc;
4127}
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:99
static int tls_newdata_process_data(struct tls_connection *tls)
Handle received TLS data payload.
Definition tls.c:4026
static int tls_newdata_process_header(struct tls_connection *tls)
Handle received TLS header.
Definition tls.c:3943
static void tls_close_alert(struct tls_connection *tls, int rc)
Send closure alert and finish with TLS connection.
Definition tls.c:403

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 4158 of file tls.c.

4158 {
4159
4160 /* Mark validation as complete */
4161 pending_put ( &tls->server.validation );
4162
4163 /* Close validator interface */
4164 intf_restart ( &tls->server.validator, rc );
4165
4166 /* Check for validation failure */
4167 if ( rc != 0 ) {
4168 DBGC ( tls, "TLS %p certificate validation failed: %s\n",
4169 tls, strerror ( rc ) );
4170 goto err;
4171 }
4172 DBGC ( tls, "TLS %p certificate validation succeeded\n", tls );
4173
4174 /* Schedule transmission of applicable handshake messages */
4178 if ( tls->client.chain ) {
4180 if ( ! list_empty ( &tls->client.chain->links ) )
4182 }
4183 tls_tx_resume ( tls );
4184
4185 return;
4186
4187 err:
4188 tls_close_alert ( tls, rc );
4189 return;
4190}
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:189
@ TLS_TX_CERTIFICATE_VERIFY
Definition tls.h:190
@ TLS_TX_CERTIFICATE
Definition tls.h:188

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_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 4214 of file tls.c.

4214 {
4215 struct tls_session *session = tls->session;
4216 struct tls_connection *conn;
4217 int rc;
4218
4219 /* Wait for cipherstream to become ready */
4220 if ( ! xfer_window ( &tls->cipherstream ) )
4221 return;
4222
4223 /* Send first pending transmission */
4224 if ( tls->tx.pending & TLS_TX_CLIENT_HELLO ) {
4225 /* Serialise server negotiations within a session, to
4226 * provide a consistent view of session IDs and
4227 * session tickets.
4228 */
4229 list_for_each_entry ( conn, &session->conn, list ) {
4230 if ( conn == tls )
4231 break;
4232 if ( is_pending ( &conn->server.negotiation ) )
4233 return;
4234 }
4235 /* Record or generate session ID and associated master secret */
4236 if ( session->id_len ) {
4237 /* Attempt to resume an existing session */
4238 memcpy ( tls->session_id, session->id,
4239 sizeof ( tls->session_id ) );
4241 } else {
4242 /* No existing session: use a random session ID */
4243 assert ( sizeof ( tls->session_id ) ==
4244 sizeof ( tls->client.random ) );
4245 memcpy ( tls->session_id, &tls->client.random,
4246 sizeof ( tls->session_id ) );
4247 tls->session_id_len = sizeof ( tls->session_id );
4248 }
4249 /* Send Client Hello */
4250 if ( ( rc = tls_send_client_hello ( tls ) ) != 0 ) {
4251 DBGC ( tls, "TLS %p could not send Client Hello: %s\n",
4252 tls, strerror ( rc ) );
4253 goto err;
4254 }
4256 } else if ( tls->tx.pending & TLS_TX_CERTIFICATE ) {
4257 /* Send Certificate */
4258 if ( ( rc = tls_send_certificate ( tls ) ) != 0 ) {
4259 DBGC ( tls, "TLS %p cold not send Certificate: %s\n",
4260 tls, strerror ( rc ) );
4261 goto err;
4262 }
4264 } else if ( tls->tx.pending & TLS_TX_CLIENT_KEY_EXCHANGE ) {
4265 /* Send Client Key Exchange */
4266 if ( ( rc = tls_send_client_key_exchange ( tls ) ) != 0 ) {
4267 DBGC ( tls, "TLS %p could not send Client Key "
4268 "Exchange: %s\n", tls, strerror ( rc ) );
4269 goto err;
4270 }
4272 } else if ( tls->tx.pending & TLS_TX_CERTIFICATE_VERIFY ) {
4273 /* Send Certificate Verify */
4274 if ( ( rc = tls_send_certificate_verify ( tls ) ) != 0 ) {
4275 DBGC ( tls, "TLS %p could not send Certificate "
4276 "Verify: %s\n", tls, strerror ( rc ) );
4277 goto err;
4278 }
4280 } else if ( tls->tx.pending & TLS_TX_CHANGE_CIPHER ) {
4281 /* Send Change Cipher, and then change the cipher in use */
4282 if ( ( rc = tls_send_change_cipher ( tls ) ) != 0 ) {
4283 DBGC ( tls, "TLS %p could not send Change Cipher: "
4284 "%s\n", tls, strerror ( rc ) );
4285 goto err;
4286 }
4287 if ( ( rc = tls_change_cipher ( tls,
4288 &tls->tx.cipherspec ) ) != 0 ){
4289 DBGC ( tls, "TLS %p could not activate TX cipher: "
4290 "%s\n", tls, strerror ( rc ) );
4291 goto err;
4292 }
4293 tls->tx.seq = 0;
4295 } else if ( tls->tx.pending & TLS_TX_FINISHED ) {
4296 /* Send Finished */
4297 if ( ( rc = tls_send_finished ( tls ) ) != 0 ) {
4298 DBGC ( tls, "TLS %p could not send Finished: %s\n",
4299 tls, strerror ( rc ) );
4300 goto err;
4301 }
4302 tls->tx.pending &= ~TLS_TX_FINISHED;
4303 }
4304
4305 /* Reschedule process if pending transmissions remain,
4306 * otherwise send notification of a window change.
4307 */
4308 if ( tls->tx.pending ) {
4309 tls_tx_resume ( tls );
4310 } else {
4312 }
4313
4314 return;
4315
4316 err:
4317 tls_close_alert ( tls, rc );
4318}
static int tls_send_certificate(struct tls_connection *tls)
Transmit Certificate record.
Definition tls.c:2171
static int tls_send_finished(struct tls_connection *tls)
Transmit Finished record.
Definition tls.c:2357
static int tls_send_client_hello(struct tls_connection *tls)
Transmit Client Hello record.
Definition tls.c:2160
static int tls_send_client_key_exchange(struct tls_connection *tls)
Transmit Client Key Exchange record.
Definition tls.c:2228
static int tls_send_change_cipher(struct tls_connection *tls)
Transmit Change Cipher record.
Definition tls.c:2340
static int tls_send_certificate_verify(struct tls_connection *tls)
Transmit Certificate Verify record.
Definition tls.c:2259

References assert, tls_tx::cipherspec, tls_connection::cipherstream, tls_connection::client, tls_session::conn, DBGC, tls_session::id, tls_session::id_len, is_pending(), tls_connection::list, list_for_each_entry, memcpy(), tls_server::negotiation, tls_tx::pending, tls_connection::plainstream, tls_client::random, rc, tls_tx::seq, tls_connection::server, tls_connection::session, tls_connection::session_id, tls_connection::session_id_len, strerror(), tls_change_cipher(), 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().

◆ 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 4338 of file tls.c.

4338 {
4339 struct tls_session *session;
4340 char *name_copy;
4341 int rc;
4342
4343 /* Find existing matching session, if any */
4344 list_for_each_entry ( session, &tls_sessions, list ) {
4345 if ( ( strcmp ( name, session->name ) == 0 ) &&
4346 ( tls->server.root == session->root ) &&
4347 ( tls->client.key == session->key ) ) {
4348 ref_get ( &session->refcnt );
4349 tls->session = session;
4350 DBGC ( tls, "TLS %p joining session %s\n", tls, name );
4351 return 0;
4352 }
4353 }
4354
4355 /* Create new session */
4356 session = zalloc ( sizeof ( *session ) + strlen ( name )
4357 + 1 /* NUL */ );
4358 if ( ! session ) {
4359 rc = -ENOMEM;
4360 goto err_alloc;
4361 }
4362 ref_init ( &session->refcnt, free_tls_session );
4363 name_copy = ( ( ( void * ) session ) + sizeof ( *session ) );
4364 strcpy ( name_copy, name );
4365 session->name = name_copy;
4366 session->root = x509_root_get ( tls->server.root );
4367 session->key = privkey_get ( tls->client.key );
4368 INIT_LIST_HEAD ( &session->conn );
4369 list_add ( &session->list, &tls_sessions );
4370
4371 /* Poison resumption master secret */
4372 tls_ephemeral_label ( tls, "res poison",
4373 session->resumption_master_secret,
4374 sizeof ( session->resumption_master_secret ) );
4375
4376 /* Record session */
4377 tls->session = session;
4378
4379 DBGC ( tls, "TLS %p created session %s\n", tls, name );
4380 return 0;
4381
4382 ref_put ( &session->refcnt );
4383 err_alloc:
4384 return rc;
4385}
const char * name
Definition ath9k_hw.c:1986
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:308
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, DBGC, ENOMEM, free_tls_session(), INIT_LIST_HEAD, tls_client::key, tls_session::key, 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_session::resumption_master_secret, tls_server::root, tls_session::root, tls_connection::server, tls_connection::session, strcmp(), strcpy(), strlen(), tls_ephemeral_label(), x509_root_get(), and zalloc().

◆ 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 4403 of file tls.c.

4404 {
4405 struct tls_connection *tls;
4406 int rc;
4407
4408 /* Allocate and initialise TLS structure */
4409 tls = malloc ( sizeof ( *tls ) );
4410 if ( ! tls ) {
4411 rc = -ENOMEM;
4412 goto err_alloc;
4413 }
4414 memset ( tls, 0, sizeof ( *tls ) );
4415 ref_init ( &tls->refcnt, free_tls );
4416 INIT_LIST_HEAD ( &tls->list );
4421 &tls->refcnt );
4422 tls->client.key = privkey_get ( key ? key : &private_key );
4424 tls->version = TLS_VERSION_MAX;
4425 tls_clear_cipher ( tls, &tls->tx.cipherspec.active );
4426 tls_clear_cipher ( tls, &tls->tx.cipherspec.pending );
4427 tls_clear_cipher ( tls, &tls->rx.cipherspec.active );
4428 tls_clear_cipher ( tls, &tls->rx.cipherspec.pending );
4429 tls_clear_digest ( tls );
4430 iob_populate ( &tls->rx.iobuf, &tls->rx.header, 0,
4431 sizeof ( tls->rx.header ) );
4432 INIT_LIST_HEAD ( &tls->rx.data );
4433 if ( ( rc = tls_generate_ephemeral_master ( tls ) ) != 0 )
4434 goto err_ephemeral;
4435 if ( ( rc = tls_session ( tls, name ) ) != 0 )
4436 goto err_session;
4437 list_add_tail ( &tls->list, &tls->session->conn );
4438
4439 /* Start negotiation */
4440 tls_restart ( tls );
4441
4442 /* Attach to parent interface, mortalise self, and return */
4443 intf_insert ( xfer, &tls->plainstream, &tls->cipherstream );
4444 ref_put ( &tls->refcnt );
4445 return 0;
4446
4447 err_session:
4448 err_ephemeral:
4449 ref_put ( &tls->refcnt );
4450 err_alloc:
4451 return rc;
4452}
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:195
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:527
static struct interface_descriptor tls_cipherstream_desc
TLS ciphertext stream interface descriptor.
Definition tls.c:4141
static struct interface_descriptor tls_validator_desc
TLS certificate validator interface descriptor.
Definition tls.c:4198
static struct interface_descriptor tls_plainstream_desc
TLS plaintext stream interface descriptor.
Definition tls.c:3926
static void free_tls(struct refcnt *refcnt)
Free TLS connection.
Definition tls.c:333
static int tls_generate_ephemeral_master(struct tls_connection *tls)
Generate ephemeral master secret.
Definition tls.c:425
static struct process_descriptor tls_process_desc
TLS TX process descriptor.
Definition tls.c:4321

References tls_cipherspec_pair::active, tls_rx::cipherspec, tls_tx::cipherspec, tls_connection::cipherstream, tls_connection::client, tls_session::conn, tls_rx::data, ENOMEM, free_tls(), tls_rx::header, INIT_LIST_HEAD, intf_init(), intf_insert(), iob_populate(), tls_rx::iobuf, key, tls_client::key, tls_connection::list, list_add_tail, malloc(), memset(), name, tls_cipherspec_pair::pending, 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, tls_connection::rx, tls_connection::server, tls_connection::session, tls_cipherstream_desc, tls_clear_cipher(), tls_clear_digest(), tls_generate_ephemeral_master(), tls_plainstream_desc, tls_process_desc, tls_restart(), tls_validator_desc, TLS_VERSION_MAX, tls_connection::tx, tls_server::validator, tls_connection::version, 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

◆ tls_cipher_suite_null

struct tls_cipher_suite tls_cipher_suite_null
Initial value:
= {
.pubkey = &pubkey_null,
.cipher = &cipher_null,
.digest = &digest_null,
}
struct cipher_algorithm cipher_null
Definition crypto_null.c:94
struct pubkey_algorithm pubkey_null
struct tls_key_exchange_algorithm tls_pubkey_exchange_algorithm
Public key exchange algorithm.
Definition tls.c:1665

Null cipher suite.

Definition at line 1191 of file tls.c.

1191 {
1192 .exchange = &tls_pubkey_exchange_algorithm,
1193 .pubkey = &pubkey_null,
1194 .cipher = &cipher_null,
1195 .digest = &digest_null,
1196};

Referenced by tls_change_cipher(), and tls_clear_cipher().

◆ tls_pubkey_exchange_algorithm

struct tls_key_exchange_algorithm tls_pubkey_exchange_algorithm
Initial value:
= {
.name = "pubkey",
}
static int tls_new_server_key_exchange_pubkey(struct tls_connection *tls, const void *data, size_t len)
Receive new Server Key Exchange record using public key transport.
Definition tls.c:1558
static int tls_send_client_key_exchange_pubkey(struct tls_connection *tls)
Transmit Client Key Exchange record using public key exchange.
Definition tls.c:1573

Public key exchange algorithm.

Definition at line 1665 of file tls.c.

1665 {
1666 .name = "pubkey",
1669};

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

◆ tls_dhe_exchange_algorithm

struct tls_key_exchange_algorithm tls_dhe_exchange_algorithm
Initial value:
= {
.name = "dhe",
}
static int tls_send_client_key_exchange_dhe(struct tls_connection *tls)
Transmit Client Key Exchange record using DHE key exchange.
Definition tls.c:1751
static int tls_new_server_key_exchange_dhe(struct tls_connection *tls, const void *data, size_t len)
Receive new Server Key Exchange record using DHE key exchange.
Definition tls.c:1679

Ephemeral Diffie-Hellman key exchange algorithm.

Definition at line 1793 of file tls.c.

1793 {
1794 .name = "dhe",
1797};

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",
}
static int tls_new_server_key_exchange_ecdhe(struct tls_connection *tls, const void *data, size_t len)
Receive new Server Key Exchange record using ECDHE key exchange.
Definition tls.c:1807
static int tls_send_client_key_exchange_ecdhe(struct tls_connection *tls)
Transmit Client Key Exchange record using ECDHE key exchange.
Definition tls.c:1867

Ephemeral Elliptic Curve Diffie-Hellman key exchange algorithm.

Definition at line 1898 of file tls.c.

1898 {
1899 .name = "ecdhe",
1902};

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

◆ 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:3903
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:3875
static size_t tls_plainstream_window(struct tls_connection *tls)
Check flow control window.
Definition tls.c:3858
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 3915 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:3915

TLS plaintext stream interface descriptor.

Definition at line 3926 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:4079
static size_t tls_cipherstream_window(struct tls_connection *tls)
Check flow control window.
Definition tls.c:4062

TLS ciphertext stream interface operations.

Definition at line 4130 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:4130

TLS ciphertext stream interface descriptor.

Definition at line 4141 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:4158

TLS certificate validator interface operations.

Definition at line 4193 of file tls.c.

4193 {
4195};

◆ 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:4193

TLS certificate validator interface descriptor.

Definition at line 4198 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:4214
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 4321 of file tls.c.

Referenced by add_tls().