iPXE
tls.c File Reference

Transport Layer Security Protocol. More...

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

Go to the source code of this file.

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 ENOENT_KEY_EXCHANGE   __einfo_error ( EINFO_ENOENT_KEY_EXCHANGE )
#define EINFO_ENOENT_KEY_EXCHANGE
#define ENOMEM_CONTEXT   __einfo_error ( EINFO_ENOMEM_CONTEXT )
#define EINFO_ENOMEM_CONTEXT
#define ENOMEM_CERTIFICATE   __einfo_error ( EINFO_ENOMEM_CERTIFICATE )
#define EINFO_ENOMEM_CERTIFICATE
#define ENOMEM_CHAIN   __einfo_error ( EINFO_ENOMEM_CHAIN )
#define EINFO_ENOMEM_CHAIN
#define ENOMEM_TX_PLAINTEXT   __einfo_error ( EINFO_ENOMEM_TX_PLAINTEXT )
#define EINFO_ENOMEM_TX_PLAINTEXT
#define ENOMEM_TX_CIPHERTEXT   __einfo_error ( EINFO_ENOMEM_TX_CIPHERTEXT )
#define EINFO_ENOMEM_TX_CIPHERTEXT
#define ENOMEM_RX_DATA   __einfo_error ( EINFO_ENOMEM_RX_DATA )
#define EINFO_ENOMEM_RX_DATA
#define ENOMEM_RX_CONCAT   __einfo_error ( EINFO_ENOMEM_RX_CONCAT )
#define EINFO_ENOMEM_RX_CONCAT
#define ENOTSUP_CIPHER   __einfo_error ( EINFO_ENOTSUP_CIPHER )
#define EINFO_ENOTSUP_CIPHER
#define ENOTSUP_NULL   __einfo_error ( EINFO_ENOTSUP_NULL )
#define EINFO_ENOTSUP_NULL
#define ENOTSUP_SIG_HASH   __einfo_error ( EINFO_ENOTSUP_SIG_HASH )
#define EINFO_ENOTSUP_SIG_HASH
#define ENOTSUP_VERSION   __einfo_error ( EINFO_ENOTSUP_VERSION )
#define EINFO_ENOTSUP_VERSION
#define ENOTSUP_GROUP   __einfo_error ( EINFO_ENOTSUP_GROUP )
#define EINFO_ENOTSUP_GROUP
#define EPERM_ALERT   __einfo_error ( EINFO_EPERM_ALERT )
#define EINFO_EPERM_ALERT
#define EPERM_VERIFY   __einfo_error ( EINFO_EPERM_VERIFY )
#define EINFO_EPERM_VERIFY
#define EPERM_RENEG_INSECURE   __einfo_error ( EINFO_EPERM_RENEG_INSECURE )
#define EINFO_EPERM_RENEG_INSECURE
#define EPERM_RENEG_VERIFY   __einfo_error ( EINFO_EPERM_RENEG_VERIFY )
#define EINFO_EPERM_RENEG_VERIFY
#define EPERM_KEY_EXCHANGE   __einfo_error ( EINFO_EPERM_KEY_EXCHANGE )
#define EINFO_EPERM_KEY_EXCHANGE
#define EPERM_SAVE   __einfo_error ( EINFO_EPERM_SAVE )
#define EINFO_EPERM_SAVE
#define EPROTO_VERSION   __einfo_error ( EINFO_EPROTO_VERSION )
#define EINFO_EPROTO_VERSION
#define TLS_NUM_CIPHER_SUITES   table_num_entries ( TLS_CIPHER_SUITES )
 Number of supported cipher suites.
#define TLS_NUM_SIG_HASH_ALGORITHMS   table_num_entries ( TLS_SIG_HASH_ALGORITHMS )
 Number of supported signature and hash algorithms.

Functions

 FILE_LICENCE (GPL2_OR_LATER)
 FILE_SECBOOT (PERMITTED)
static LIST_HEAD (tls_sessions)
 List of TLS session.
static void tls_tx_resume_all (struct tls_session *session)
 Resume TX state machine for all connections within a session.
static struct io_buffertls_alloc_iob (struct tls_connection *tls, size_t len)
 Allocate I/O buffer for transmitted record(s).
static int tls_send_alert (struct tls_connection *tls, unsigned int level, unsigned int description)
 Transmit Alert record.
static int tls_send_record (struct tls_connection *tls, unsigned int type, struct io_buffer *iobuf)
 Send plaintext record(s).
static int tls_send_plaintext (struct tls_connection *tls, unsigned int type, const void *data, size_t len)
 Send plaintext record.
static void tls_clear_digest (struct tls_connection *tls)
 Clear key schedule digest algorithm.
static void tls_clear_cipher (struct tls_connection *tls, struct tls_cipherspec *cipherspec)
static 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 const char * tls_pipe_name (struct tls_connection *tls, struct secure_pipe *pipe)
 Get pipe name (for debugging).
static void free_tls_session (struct refcnt *refcnt)
 Free TLS session.
static void free_tls (struct refcnt *refcnt)
 Free TLS connection.
static void tls_close (struct tls_connection *tls, int rc)
 Finish with TLS connection.
static void tls_close_alert (struct tls_connection *tls, int rc)
 Send closure alert and finish with TLS connection.
static void tls_nonce (struct tls_connection *tls, struct tls_random *nonce)
 Generate deterministic connection nonce.
static int tls_set_digest (struct tls_connection *tls, struct digest_algorithm *digest)
 Set key schedule digest algorithm.
static const char * tls_cipher_name (struct tls_cipher_suite *suite)
 Get cipher suite name (for debugging).
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 specification.
static int tls_set_cipher (struct tls_connection *tls, struct tls_cipherspec *cipherspec, struct tls_cipher_suite *suite)
 Set cipher specification.
static int tls_select_cipher (struct tls_connection *tls, unsigned int cipher_suite)
 Select cipher suite.
static int tls_change_cipher (struct tls_connection *tls, struct tls_cipherspec_pair *pair, struct secure_pipe *pipe)
 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_parse_null (struct tls_connection *tls, const void *data, size_t len, struct tls_key_exchange_parameters *params __unused)
 Parse key exchange parameters from unexpected Server Key Exchange record.
static int tls_parse_dhe (struct tls_connection *tls, const void *data, size_t len, struct tls_key_exchange_parameters *params)
 Parse key exchange parameters from DHE Server Key Exchange record.
static int tls_parse_ecdhe (struct tls_connection *tls, const void *data, size_t len, struct tls_key_exchange_parameters *params)
 Parse key exchange parameters from ECDHE Server Key Exchange record.
static int tls_keysize_is_variable (struct tls_connection *tls, struct exchange_algorithm *exchange)
 Check if key exchange keys have a variable size.
static int tls_key_share (struct tls_connection *tls, struct exchange_algorithm *exchange, void *public, size_t len)
 Share public key.
static int tls_key_agree (struct tls_connection *tls, struct exchange_algorithm *exchange, const void *partner, size_t len)
 Agree shared secret.
static int tls_key_encrypt (struct tls_connection *tls, struct exchange_algorithm *exchange, struct asn1_builder *builder)
 Encrypt (and implicitly bind) shared secret.
static int tls_key_build (struct tls_connection *tls, struct exchange_algorithm *exchange, struct asn1_builder *builder)
 Build shareable key.
static void tls_channel_reset (struct secure_channel *channel)
 Reset the key schedule.
static int tls_channel_apply (struct secure_channel *channel, struct exchange_algorithm *exchange, const void *shared, int *accumulated)
 Apply a new shared secret to key schedule.
static int tls_channel_save (struct secure_channel *channel, struct secure_preshared_identity *psid)
 Save a pre-shared key for future resumption of the key schedule.
static int tls_channel_load (struct secure_channel *channel, struct secure_preshared_identity *psid)
 Load a pre-shared key and resume the key schedule.
static int tls_channel_verify (struct secure_channel *channel, const void *auth, size_t len)
 Verify authenticator value.
static int tls_session (struct tls_connection *tls, const char *name)
 Find or create session for TLS connection.
static int tls_save (struct tls_connection *tls)
 Save session for future resumption.
static int tls_resume (struct tls_connection *tls)
 Resume session.
static int tls_add_handshake (struct tls_connection *tls, const void *data, size_t len)
 Add handshake record to verification hash.
static void tls_tx_resume (struct tls_connection *tls)
 Resume TX state machine.
static void tls_restart (struct tls_connection *tls)
 Restart negotiation.
static int tls_establish (struct tls_connection *tls)
 Establish secure channel.
static int tls_send_handshake (struct tls_connection *tls, const void *data, size_t len)
 Transmit Handshake record.
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.
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_null_exchange_algorithm
 Null key exchange algorithm.
struct tls_key_exchange_algorithm tls_pubkey_exchange_algorithm
 Public key exchange algorithm.
struct tls_key_exchange_algorithm tls_dhe_exchange_algorithm
 Ephemeral Diffie-Hellman key exchange algorithm.
struct tls_key_exchange_algorithm tls_ecdhe_exchange_algorithm
 Ephemeral Elliptic Curve Diffie-Hellman key exchange algorithm.
static struct secure_channel_operations tls_channel_ops
 Secure channel operations.
static struct interface_operation tls_plainstream_ops []
 TLS plaintext stream interface operations.
static struct interface_descriptor tls_plainstream_desc
 TLS plaintext stream interface descriptor.
static struct interface_operation tls_cipherstream_ops []
 TLS ciphertext stream interface operations.
static struct interface_descriptor tls_cipherstream_desc
 TLS ciphertext stream interface descriptor.
static struct interface_operation tls_validator_ops []
 TLS certificate validator interface operations.
static struct interface_descriptor tls_validator_desc
 TLS certificate validator interface descriptor.
static struct process_descriptor tls_process_desc
 TLS TX process descriptor.

Detailed Description

Transport Layer Security Protocol.

Definition in file tls.c.

Macro Definition Documentation

◆ EINVAL_CHANGE_CIPHER

#define EINVAL_CHANGE_CIPHER   __einfo_error ( EINFO_EINVAL_CHANGE_CIPHER )

Definition at line 53 of file tls.c.

Referenced by tls_new_change_cipher().

◆ EINFO_EINVAL_CHANGE_CIPHER

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

Definition at line 54 of file tls.c.

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

◆ EINVAL_ALERT

#define EINVAL_ALERT   __einfo_error ( EINFO_EINVAL_ALERT )

Definition at line 57 of file tls.c.

Referenced by tls_new_alert().

◆ EINFO_EINVAL_ALERT

#define EINFO_EINVAL_ALERT
Value:
"Invalid Alert record" )

Definition at line 58 of file tls.c.

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

◆ EINVAL_HELLO

#define EINVAL_HELLO   __einfo_error ( EINFO_EINVAL_HELLO )

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

62#define EINFO_EINVAL_HELLO \
63 __einfo_uniqify ( EINFO_EINVAL, 0x03, \
64 "Invalid Server Hello record" )

◆ EINVAL_CERTIFICATE

#define EINVAL_CERTIFICATE   __einfo_error ( EINFO_EINVAL_CERTIFICATE )

Definition at line 65 of file tls.c.

Referenced by tls_parse_chain().

◆ EINFO_EINVAL_CERTIFICATE

#define EINFO_EINVAL_CERTIFICATE
Value:
"Invalid Certificate" )

Definition at line 66 of file tls.c.

66#define EINFO_EINVAL_CERTIFICATE \
67 __einfo_uniqify ( EINFO_EINVAL, 0x04, \
68 "Invalid Certificate" )

◆ EINVAL_CERTIFICATES

#define EINVAL_CERTIFICATES   __einfo_error ( EINFO_EINVAL_CERTIFICATES )

Definition at line 69 of file tls.c.

Referenced by tls_new_certificate().

◆ EINFO_EINVAL_CERTIFICATES

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

Definition at line 70 of file tls.c.

70#define EINFO_EINVAL_CERTIFICATES \
71 __einfo_uniqify ( EINFO_EINVAL, 0x05, \
72 "Invalid Server Certificate record" )

◆ EINVAL_HELLO_DONE

#define EINVAL_HELLO_DONE   __einfo_error ( EINFO_EINVAL_HELLO_DONE )

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

74#define EINFO_EINVAL_HELLO_DONE \
75 __einfo_uniqify ( EINFO_EINVAL, 0x06, \
76 "Invalid Server Hello Done record" )

◆ EINVAL_FINISHED

#define EINVAL_FINISHED   __einfo_error ( EINFO_EINVAL_FINISHED )

Definition at line 77 of file tls.c.

◆ EINFO_EINVAL_FINISHED

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

Definition at line 78 of file tls.c.

78#define EINFO_EINVAL_FINISHED \
79 __einfo_uniqify ( EINFO_EINVAL, 0x07, \
80 "Invalid Server Finished record" )

◆ EINVAL_HANDSHAKE

#define EINVAL_HANDSHAKE   __einfo_error ( EINFO_EINVAL_HANDSHAKE )

Definition at line 81 of file tls.c.

◆ EINFO_EINVAL_HANDSHAKE

#define EINFO_EINVAL_HANDSHAKE
Value:
"Invalid Handshake record" )

Definition at line 82 of file tls.c.

82#define EINFO_EINVAL_HANDSHAKE \
83 __einfo_uniqify ( EINFO_EINVAL, 0x08, \
84 "Invalid Handshake record" )

◆ EINVAL_IV

#define EINVAL_IV   __einfo_error ( EINFO_EINVAL_IV )

Definition at line 85 of file tls.c.

Referenced by tls_new_ciphertext().

◆ EINFO_EINVAL_IV

#define EINFO_EINVAL_IV
Value:
"Invalid initialisation vector" )

Definition at line 86 of file tls.c.

86#define EINFO_EINVAL_IV \
87 __einfo_uniqify ( EINFO_EINVAL, 0x0a, \
88 "Invalid initialisation vector" )

◆ EINVAL_PADDING

#define EINVAL_PADDING   __einfo_error ( EINFO_EINVAL_PADDING )

Definition at line 89 of file tls.c.

Referenced by tls_verify_padding().

◆ EINFO_EINVAL_PADDING

#define EINFO_EINVAL_PADDING
Value:
"Invalid block padding" )

Definition at line 90 of file tls.c.

90#define EINFO_EINVAL_PADDING \
91 __einfo_uniqify ( EINFO_EINVAL, 0x0b, \
92 "Invalid block padding" )

◆ EINVAL_RX_STATE

#define EINVAL_RX_STATE   __einfo_error ( EINFO_EINVAL_RX_STATE )

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

94#define EINFO_EINVAL_RX_STATE \
95 __einfo_uniqify ( EINFO_EINVAL, 0x0c, \
96 "Invalid receive state" )

◆ EINVAL_MAC

#define EINVAL_MAC   __einfo_error ( EINFO_EINVAL_MAC )

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

98#define EINFO_EINVAL_MAC \
99 __einfo_uniqify ( EINFO_EINVAL, 0x0d, \
100 "Invalid MAC or authentication tag" )

◆ EINVAL_TICKET

#define EINVAL_TICKET   __einfo_error ( EINFO_EINVAL_TICKET )

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

102#define EINFO_EINVAL_TICKET \
103 __einfo_uniqify ( EINFO_EINVAL, 0x0e, \
104 "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 106 of file tls.c.

106#define EINFO_EINVAL_KEY_EXCHANGE \
107 __einfo_uniqify ( EINFO_EINVAL, 0x0f, \
108 "Invalid Server Key Exchange record" )

◆ EIO_ALERT

#define EIO_ALERT   __einfo_error ( EINFO_EIO_ALERT )

Definition at line 109 of file tls.c.

Referenced by tls_new_alert().

◆ EINFO_EIO_ALERT

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

Definition at line 110 of file tls.c.

110#define EINFO_EIO_ALERT \
111 __einfo_uniqify ( EINFO_EIO, 0x01, \
112 "Unknown alert level" )

◆ ENOENT_CERT

◆ EINFO_ENOENT_CERT

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

Definition at line 114 of file tls.c.

114#define EINFO_ENOENT_CERT \
115 __einfo_uniqify ( EINFO_ENOENT, 0x01, \
116 "Missing certificate" )

◆ ENOENT_KEY_EXCHANGE

#define ENOENT_KEY_EXCHANGE   __einfo_error ( EINFO_ENOENT_KEY_EXCHANGE )

Definition at line 117 of file tls.c.

Referenced by tls_send_client_key_exchange().

◆ EINFO_ENOENT_KEY_EXCHANGE

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

Definition at line 118 of file tls.c.

118#define EINFO_ENOENT_KEY_EXCHANGE \
119 __einfo_uniqify ( EINFO_ENOENT, 0x02, \
120 "No key exchange algorithm selected" )

◆ ENOMEM_CONTEXT

#define ENOMEM_CONTEXT   __einfo_error ( EINFO_ENOMEM_CONTEXT )

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

Definition at line 122 of file tls.c.

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

◆ ENOMEM_CERTIFICATE

#define ENOMEM_CERTIFICATE   __einfo_error ( EINFO_ENOMEM_CERTIFICATE )

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

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

◆ ENOMEM_CHAIN

#define ENOMEM_CHAIN   __einfo_error ( EINFO_ENOMEM_CHAIN )

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

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

◆ ENOMEM_TX_PLAINTEXT

#define ENOMEM_TX_PLAINTEXT   __einfo_error ( EINFO_ENOMEM_TX_PLAINTEXT )

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

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

◆ ENOMEM_TX_CIPHERTEXT

#define ENOMEM_TX_CIPHERTEXT   __einfo_error ( EINFO_ENOMEM_TX_CIPHERTEXT )

Definition at line 137 of file tls.c.

◆ EINFO_ENOMEM_TX_CIPHERTEXT

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

Definition at line 138 of file tls.c.

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

◆ ENOMEM_RX_DATA

#define ENOMEM_RX_DATA   __einfo_error ( EINFO_ENOMEM_RX_DATA )

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

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

◆ ENOMEM_RX_CONCAT

#define ENOMEM_RX_CONCAT   __einfo_error ( EINFO_ENOMEM_RX_CONCAT )

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

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

◆ ENOTSUP_CIPHER

#define ENOTSUP_CIPHER   __einfo_error ( EINFO_ENOTSUP_CIPHER )

Definition at line 149 of file tls.c.

Referenced by tls_select_cipher().

◆ EINFO_ENOTSUP_CIPHER

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

Definition at line 150 of file tls.c.

150#define EINFO_ENOTSUP_CIPHER \
151 __einfo_uniqify ( EINFO_ENOTSUP, 0x01, \
152 "Unsupported cipher" )

◆ ENOTSUP_NULL

#define ENOTSUP_NULL   __einfo_error ( EINFO_ENOTSUP_NULL )

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

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

◆ ENOTSUP_SIG_HASH

#define ENOTSUP_SIG_HASH   __einfo_error ( EINFO_ENOTSUP_SIG_HASH )

Definition at line 157 of file tls.c.

Referenced by tls_new_server_key_exchange(), and tls_send_certificate_verify().

◆ EINFO_ENOTSUP_SIG_HASH

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

Definition at line 158 of file tls.c.

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

◆ ENOTSUP_VERSION

#define ENOTSUP_VERSION   __einfo_error ( EINFO_ENOTSUP_VERSION )

Definition at line 161 of file tls.c.

◆ EINFO_ENOTSUP_VERSION

#define EINFO_ENOTSUP_VERSION
Value:
"Unsupported protocol version" )

Definition at line 162 of file tls.c.

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

◆ ENOTSUP_GROUP

#define ENOTSUP_GROUP   __einfo_error ( EINFO_ENOTSUP_GROUP )

Definition at line 165 of file tls.c.

Referenced by tls_parse_dhe(), and tls_parse_ecdhe().

◆ EINFO_ENOTSUP_GROUP

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

Definition at line 166 of file tls.c.

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

◆ EPERM_ALERT

#define EPERM_ALERT   __einfo_error ( EINFO_EPERM_ALERT )

Definition at line 169 of file tls.c.

Referenced by tls_new_alert().

◆ EINFO_EPERM_ALERT

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

Definition at line 170 of file tls.c.

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

◆ EPERM_VERIFY

#define EPERM_VERIFY   __einfo_error ( EINFO_EPERM_VERIFY )

Definition at line 173 of file tls.c.

Referenced by tls_channel_verify().

◆ EINFO_EPERM_VERIFY

#define EINFO_EPERM_VERIFY
Value:
"Handshake verification failed" )

Definition at line 174 of file tls.c.

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

◆ EPERM_RENEG_INSECURE

#define EPERM_RENEG_INSECURE   __einfo_error ( EINFO_EPERM_RENEG_INSECURE )

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

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

◆ EPERM_RENEG_VERIFY

#define EPERM_RENEG_VERIFY   __einfo_error ( EINFO_EPERM_RENEG_VERIFY )

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

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

◆ EPERM_KEY_EXCHANGE

#define EPERM_KEY_EXCHANGE   __einfo_error ( EINFO_EPERM_KEY_EXCHANGE )

Definition at line 185 of file tls.c.

Referenced by tls_new_server_key_exchange().

◆ EINFO_EPERM_KEY_EXCHANGE

#define EINFO_EPERM_KEY_EXCHANGE
Value:
"ServerKeyExchange verification failed" )

Definition at line 186 of file tls.c.

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

◆ EPERM_SAVE

#define EPERM_SAVE   __einfo_error ( EINFO_EPERM_SAVE )

Definition at line 189 of file tls.c.

Referenced by tls_channel_save().

◆ EINFO_EPERM_SAVE

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

Definition at line 190 of file tls.c.

190#define EINFO_EPERM_SAVE \
191 __einfo_uniqify ( EINFO_EPERM, 0x07, \
192 "Pre-shared key was not established" )

◆ EPROTO_VERSION

#define EPROTO_VERSION   __einfo_error ( EINFO_EPROTO_VERSION )

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

Definition at line 194 of file tls.c.

194#define EINFO_EPROTO_VERSION \
195 __einfo_uniqify ( EINFO_EPROTO, 0x01, \
196 "Illegal protocol version upgrade" )

◆ TLS_NUM_CIPHER_SUITES

#define TLS_NUM_CIPHER_SUITES   table_num_entries ( TLS_CIPHER_SUITES )

Number of supported cipher suites.

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

750#define TLS_NUM_SIG_HASH_ALGORITHMS \
751 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_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 1552 of file tls.c.

1552 {
1553 struct tls_connection *tls;
1554
1556 tls_tx_resume ( tls );
1557}
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition list.h:432
A TLS connection.
Definition tls.h:445
struct tls_session * session
Session.
Definition tls.h:450
struct list_head list
List of connections within the same session.
Definition tls.h:452
struct list_head conn
List of connections.
Definition tls.h:387
static void tls_tx_resume(struct tls_connection *tls)
Resume TX state machine.
Definition tls.c:1543

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

Referenced by tls_close(), and tls_establish().

◆ tls_alloc_iob()

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

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

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

Definition at line 3253 of file tls.c.

3254 {
3255 struct io_buffer *iobuf;
3256 size_t reserve;
3257
3258 /* Calculate maximum additional length to reserve */
3259 reserve = tls_iob_reserved ( tls, len );
3260
3261 /* Allocate I/O buffer */
3262 iobuf = xfer_alloc_iob ( &tls->cipherstream, ( reserve + len ) );
3263 if ( ! iobuf )
3264 return NULL;
3265
3266 /* Reserve space */
3267 iob_reserve ( iobuf, reserve );
3268
3269 return iobuf;
3270}
#define NULL
NULL pointer (VOID *).
Definition Base.h:321
ring len
Length.
Definition dwmac.h:226
#define iob_reserve(iobuf, len)
Definition iobuf.h:132
A persistent I/O buffer.
Definition iobuf.h:98
struct interface cipherstream
Ciphertext stream.
Definition tls.h:461
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:3225
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_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 2140 of file tls.c.

2141 {
2142 const struct {
2143 uint8_t level;
2144 uint8_t description;
2145 } __attribute__ (( packed )) alert = {
2146 .level = level,
2147 .description = description,
2148 };
2149
2150 /* Send record */
2151 return tls_send_plaintext ( tls, TLS_TYPE_ALERT, &alert,
2152 sizeof ( alert ) );
2153}
unsigned char uint8_t
Definition stdint.h:10
#define __attribute__(x)
Definition compiler.h:10
void alert(unsigned int row, const char *fmt,...)
Show alert message.
Definition message.c:104
static int tls_send_plaintext(struct tls_connection *tls, unsigned int type, const void *data, size_t len)
Send plaintext record.
Definition tls.c:3432
#define TLS_TYPE_ALERT
Alert content type.
Definition tls.h:60

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

3281 {
3282 struct tls_cipherspec *cipherspec = &tls->tx.cipherspec.active;
3283 struct tls_cipher_suite *suite = cipherspec->suite;
3284 struct digest_algorithm *digest = suite->digest;
3285 struct secure_pipe *pipe = &tls->channel.tx;
3286 struct cipher_algorithm *cipher = pipe->cipher;
3287 struct {
3288 uint8_t fixed[suite->fixed_iv_len];
3289 uint8_t rec[suite->record_iv_len];
3290 } __attribute__ (( packed )) iv;
3291 struct tls_auth_header authhdr;
3292 struct tls_header *tlshdr;
3293 uint8_t mac[digest->digestsize];
3294 const void *plaintext;
3295 const void *encrypt;
3296 void *ciphertext;
3297 size_t record_len;
3298 size_t encrypt_len;
3299 size_t pad_len;
3300 size_t len;
3301 int rc;
3302
3303 /* Sanity check */
3304 assert ( cipher == suite->cipher );
3305
3306 /* Record plaintext pointer and length */
3307 plaintext = iobuf->data;
3308 len = iob_len ( iobuf );
3309
3310 /* Add to handshake digest if applicable */
3311 if ( type == TLS_TYPE_HANDSHAKE )
3312 tls_add_handshake ( tls, plaintext, len );
3313
3314 /* Start constructing ciphertext at start of reserved space */
3315 iob_push ( iobuf, tls_iob_reserved ( tls, len ) );
3316 iob_unput ( iobuf, iob_len ( iobuf ) );
3317
3318 /* Construct records */
3319 do {
3320 /* Limit length of this record (may be zero) */
3321 record_len = len;
3322 if ( record_len > TLS_TX_BUFSIZE )
3323 record_len = TLS_TX_BUFSIZE;
3324
3325 /* Construct authentication header */
3326 authhdr.seq = cpu_to_be64 ( tls->tx.seq );
3327 authhdr.header.type = type;
3328 authhdr.header.version = htons ( tls->version );
3329 authhdr.header.length = htons ( record_len );
3330
3331 /* Construct and set initialisation vector */
3332 memcpy ( iv.fixed, cipherspec->fixed_iv, sizeof ( iv.fixed ) );
3333 channel_ephemeral ( &tls->channel, &authhdr,
3334 sizeof ( authhdr ), iv.rec,
3335 sizeof ( iv.rec ) );
3336 if ( ( rc = cipher_setiv ( cipher, pipe->ctx, &iv,
3337 sizeof ( iv ) ) ) != 0 ) {
3338 DBGC ( tls, "TLS %p could not set TX IV: %s\n",
3339 tls, strerror ( rc ) );
3340 goto err_setiv;
3341 }
3342
3343 /* Process authentication data */
3344 if ( suite->mac_len ) {
3345 tls_hmac ( cipherspec, &authhdr, plaintext,
3346 record_len, mac );
3347 }
3348 if ( is_auth_cipher ( cipher ) ) {
3349 cipher_encrypt ( cipher, pipe->ctx, &authhdr, NULL,
3350 sizeof ( authhdr ) );
3351 }
3352
3353 /* Calculate encryption length */
3354 encrypt_len = ( record_len + suite->mac_len );
3355 if ( is_block_cipher ( cipher ) ) {
3356 pad_len = ( ( ( cipher->blocksize - 1 ) &
3357 -( encrypt_len + 1 ) ) + 1 );
3358 } else {
3359 pad_len = 0;
3360 }
3361 encrypt_len += pad_len;
3362
3363 /* Add record header */
3364 tlshdr = iob_put ( iobuf, sizeof ( *tlshdr ) );
3365 tlshdr->type = type;
3366 tlshdr->version = htons ( tls->version );
3367 tlshdr->length = htons ( sizeof ( iv.rec ) + encrypt_len +
3368 cipher->authsize );
3369
3370 /* Add record initialisation vector, if applicable */
3371 memcpy ( iob_put ( iobuf, sizeof ( iv.rec ) ), iv.rec,
3372 sizeof ( iv.rec ) );
3373
3374 /* Copy plaintext data if necessary */
3375 ciphertext = iob_put ( iobuf, record_len );
3376 assert ( ciphertext <= plaintext );
3377 if ( encrypt_len > record_len ) {
3378 memmove ( ciphertext, plaintext, record_len );
3379 encrypt = ciphertext;
3380 } else {
3381 encrypt = plaintext;
3382 }
3383
3384 /* Add MAC, if applicable */
3385 memcpy ( iob_put ( iobuf, suite->mac_len ), mac,
3386 suite->mac_len );
3387
3388 /* Add padding, if applicable */
3389 memset ( iob_put ( iobuf, pad_len ), ( pad_len - 1 ), pad_len );
3390
3391 /* Encrypt data and append authentication tag */
3392 DBGC2 ( tls, "Sending plaintext data:\n" );
3393 DBGC2_HDA ( tls, 0, encrypt, encrypt_len );
3394 cipher_encrypt ( cipher, pipe->ctx, encrypt, ciphertext,
3395 encrypt_len );
3396 cipher_auth ( cipher, pipe->ctx,
3397 iob_put ( iobuf, cipher->authsize ) );
3398
3399 /* Move to next record */
3400 tls->tx.seq += 1;
3401 plaintext += record_len;
3402 len -= record_len;
3403
3404 } while ( len );
3405
3406 /* Send ciphertext */
3407 if ( ( rc = xfer_deliver_iob ( &tls->cipherstream,
3408 iob_disown ( iobuf ) ) ) != 0 ) {
3409 DBGC ( tls, "TLS %p could not deliver ciphertext: %s\n",
3410 tls, strerror ( rc ) );
3411 goto err_deliver;
3412 }
3413
3414 assert ( iobuf == NULL );
3415 return 0;
3416
3417 err_deliver:
3418 err_setiv:
3419 free_iob ( iobuf );
3420 return rc;
3421}
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:61
void channel_ephemeral(struct secure_channel *channel, const void *info, size_t info_len, void *out, size_t len)
Generate ephemeral secret.
Definition channel.c:195
struct eltorito_descriptor_fixed fixed
Fixed portion.
Definition eltorito.h:1
uint32_t type
Operating system type.
Definition ena.h:1
uint8_t mac[ETH_ALEN]
MAC address.
Definition ena.h:13
#define DBGC2(...)
Definition compiler.h:547
#define DBGC2_HDA(...)
Definition compiler.h:548
#define DBGC(...)
Definition compiler.h:530
#define htons(value)
Definition byteswap.h:136
#define cpu_to_be64(value)
Definition byteswap.h:112
static int is_block_cipher(struct cipher_algorithm *cipher)
Definition crypto.h:352
static int cipher_setiv(struct cipher_algorithm *cipher, void *ctx, const void *iv, size_t ivlen)
Definition crypto.h:316
static int is_auth_cipher(struct cipher_algorithm *cipher)
Definition crypto.h:357
#define cipher_encrypt(cipher, ctx, src, dst, len)
Definition crypto.h:326
static void cipher_auth(struct cipher_algorithm *cipher, void *ctx, void *auth)
Definition crypto.h:342
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void * memset(void *dest, int character, size_t len) __nonnull
void * memmove(void *dest, const void *src, size_t len) __nonnull
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition iobuf.c:153
#define iob_push(iobuf, len)
Definition iobuf.h:149
#define iob_put(iobuf, len)
Definition iobuf.h:185
#define iob_disown(iobuf)
Disown an I/O buffer.
Definition iobuf.h:277
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition iobuf.h:220
#define iob_unput(iobuf, len)
Definition iobuf.h:200
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
A cipher algorithm.
Definition crypto.h:58
size_t blocksize
Block size.
Definition crypto.h:68
size_t authsize
Authentication tag size.
Definition crypto.h:82
A message digest algorithm.
Definition crypto.h:19
size_t digestsize
Digest size.
Definition crypto.h:27
void * data
Start of data.
Definition iobuf.h:113
struct secure_pipe tx
Transmit pipe.
Definition channel.h:82
A secure channel transmit or receive pipe.
Definition channel.h:56
void * ctx
Cipher context.
Definition channel.h:60
struct cipher_algorithm * cipher
Cipher algorithm.
Definition channel.h:58
TLS authentication header.
Definition tls.h:166
A TLS cipher suite.
Definition tls.h:239
uint8_t fixed_iv_len
Fixed initialisation vector length.
Definition tls.h:255
struct cipher_algorithm * cipher
Bulk encryption cipher algorithm.
Definition tls.h:245
uint8_t mac_len
MAC length.
Definition tls.h:259
uint8_t record_iv_len
Record initialisation vector length.
Definition tls.h:257
struct digest_algorithm * digest
MAC digest algorithm.
Definition tls.h:247
struct tls_cipherspec active
Current cipher specification.
Definition tls.h:317
A TLS cipher specification.
Definition tls.h:299
void * fixed_iv
Fixed initialisation vector.
Definition tls.h:309
struct tls_cipher_suite * suite
Cipher suite.
Definition tls.h:301
struct secure_channel channel
Secure channel.
Definition tls.h:475
struct tls_tx tx
Transmit state.
Definition tls.h:479
uint16_t version
Protocol version.
Definition tls.h:464
A TLS header.
Definition tls.h:29
uint16_t version
Protocol version.
Definition tls.h:39
uint16_t length
Length of payload.
Definition tls.h:41
uint8_t type
Content type.
Definition tls.h:34
uint64_t seq
Sequence number.
Definition tls.h:395
struct tls_cipherspec_pair cipherspec
Cipher specifications.
Definition tls.h:393
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:3184
static int tls_add_handshake(struct tls_connection *tls, const void *data, size_t len)
Add handshake record to verification hash.
Definition tls.c:1529
#define TLS_TX_BUFSIZE
TX maximum fragment length.
Definition tls.h:497
#define TLS_TYPE_HANDSHAKE
Handshake content type.
Definition tls.h:63
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_connection::channel, channel_ephemeral(), secure_pipe::cipher, tls_cipher_suite::cipher, cipher_auth(), cipher_encrypt, cipher_setiv(), tls_tx::cipherspec, tls_connection::cipherstream, cpu_to_be64, secure_pipe::ctx, io_buffer::data, DBGC, DBGC2, DBGC2_HDA, tls_cipher_suite::digest, digest_algorithm::digestsize, fixed, tls_cipherspec::fixed_iv, tls_cipher_suite::fixed_iv_len, 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_hmac(), tls_iob_reserved(), TLS_TX_BUFSIZE, TLS_TYPE_HANDSHAKE, secure_channel::tx, 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 3432 of file tls.c.

3433 {
3434 struct io_buffer *iobuf;
3435 int rc;
3436
3437 /* Allocate I/O buffer */
3438 iobuf = tls_alloc_iob ( tls, len );
3439 if ( ! iobuf )
3440 return -ENOMEM_TX_PLAINTEXT;
3441 memcpy ( iob_put ( iobuf, len ), data, len );
3442
3443 /* Transmit I/O buffer */
3444 if ( ( rc = tls_send_record ( tls, type, iob_disown ( iobuf ) ) ) != 0 )
3445 return rc;
3446
3447 return 0;
3448}
uint8_t data[48]
Additional event data.
Definition ena.h:11
static struct io_buffer * tls_alloc_iob(struct tls_connection *tls, size_t len)
Allocate I/O buffer for transmitted record(s).
Definition tls.c:3253
static int tls_send_record(struct tls_connection *tls, unsigned int type, struct io_buffer *iobuf)
Send plaintext record(s).
Definition tls.c:3280
#define ENOMEM_TX_PLAINTEXT
Definition tls.c:133

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

void tls_clear_digest ( struct tls_connection * tls)
static

Clear key schedule digest algorithm.

Parameters
tlsTLS connection

Definition at line 457 of file tls.c.

457 {
458
459 /* Inform secure channel that key material is being destroyed */
460 channel_unkey ( &tls->channel );
461
462 /* Stop key schedule */
463 tlskey_stop ( &tls->key );
464}
void channel_unkey(struct secure_channel *channel)
Clear shared secret.
Definition channel.c:273
struct tls_key_schedule key
Key schedule.
Definition tls.h:477
void tlskey_stop(struct tls_key_schedule *tlskey)
Stop key schedule.
Definition tlskey.c:259

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

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

◆ tls_clear_cipher() [1/2]

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

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

241 {
242
243 return ( ( field24->high << 16 ) | be16_to_cpu ( field24->low ) );
244}
#define be16_to_cpu(value)
Definition byteswap.h:116
uint8_t high
High byte.
Definition tls.c:228
uint16_t low
Low word.
Definition tls.c:230

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

252 {
253
254 field24->high = ( value >> 16 );
255 field24->low = cpu_to_be16 ( value );
256}
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 264 of file tls.c.

264 {
265
266 return channel_is_established ( &tls->channel );
267}
static int channel_is_established(struct secure_channel *channel)
Check if secure channel has been established.
Definition channel.h:271

References tls_connection::channel, and channel_is_established().

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

◆ tls_version()

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

Check for TLS version.

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

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

Definition at line 281 of file tls.c.

281 {
282 return ( ( TLS_VERSION_MIN >= version ) ||
283 ( tls->version >= version ) );
284}
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_keysize_is_variable(), tls_new_server_key_exchange(), tls_select_cipher(), tls_send_certificate_verify(), and tls_set_digest().

◆ tls_pipe_name()

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

Get pipe name (for debugging).

Parameters
tlsTLS connection
pipeSecure pipe
Return values
nameSecure pipe name

Definition at line 293 of file tls.c.

294 {
295
296 if ( pipe == &tls->channel.tx ) {
297 return "TX";
298 } else if ( pipe == &tls->channel.rx ) {
299 return "RX";
300 } else {
301 return "<UNKNOWN>";
302 }
303}
struct secure_pipe rx
Receive pipe.
Definition channel.h:84

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

Referenced by tls_change_cipher().

◆ free_tls_session()

void free_tls_session ( struct refcnt * refcnt)
static

Free TLS session.

Parameters
refcntReference counter

Definition at line 317 of file tls.c.

317 {
318 struct tls_session *session =
320
321 /* Sanity check */
322 assert ( list_empty ( &session->conn ) );
323
324 /* Remove from list of sessions */
325 list_del ( &session->list );
326
327 /* Clear pre-shared identity */
328 channel_clear_preshared ( &session->psid );
329
330 /* Free dynamically-allocated resources */
331 x509_root_put ( session->root );
332 privkey_put ( session->key );
333 zfree ( session->ticket.data );
334
335 /* Free session */
336 zfree ( session );
337}
static void channel_clear_preshared(struct secure_preshared_identity *psid)
Clear pre-shared bound peer identity.
Definition channel.h:282
#define list_del(list)
Delete an entry from a list.
Definition list.h:120
#define list_empty(list)
Test whether a list is empty.
Definition list.h:137
void zfree(void *ptr)
Clear and free memory.
Definition malloc.c:738
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
void * data
Ticket data.
Definition tls.h:358
A TLS session.
Definition tls.h:364
struct private_key * key
Private key.
Definition tls.h:375
struct secure_preshared_identity psid
Bound peer identity.
Definition tls.h:378
struct x509_root * root
Root of trust.
Definition tls.h:373
struct tls_session_ticket ticket
Session ticket.
Definition tls.h:384
struct list_head list
List of sessions.
Definition tls.h:368
static void x509_root_put(struct x509_root *root)
Drop reference to X.509 root certificate list.
Definition x509.h:404

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

Referenced by tls_session().

◆ free_tls()

void free_tls ( struct refcnt * refcnt)
static

Free TLS connection.

Parameters
refcntReference counter

Definition at line 344 of file tls.c.

344 {
345 struct tls_connection *tls =
347 struct tls_session *session = tls->session;
348 struct io_buffer *iobuf;
349 struct io_buffer *tmp;
350
351 /* Free dynamically-allocated resources */
352 zfree ( tls->new_ticket.data );
353 tls_clear_digest ( tls );
354 tls_clear_cipher ( tls, &tls->tx.cipherspec.active );
355 tls_clear_cipher ( tls, &tls->tx.cipherspec.pending );
356 tls_clear_cipher ( tls, &tls->rx.cipherspec.active );
357 tls_clear_cipher ( tls, &tls->rx.cipherspec.pending );
358 list_for_each_entry_safe ( iobuf, tmp, &tls->rx.data, list ) {
359 list_del ( &iobuf->list );
360 free_iob ( iobuf );
361 }
362 free_iob ( tls->rx.handshake );
363 privkey_put ( tls->client.key );
364 x509_chain_put ( tls->client.chain );
365 x509_chain_put ( tls->server.chain );
366 x509_root_put ( tls->server.root );
367
368 /* Drop reference to session */
369 assert ( list_empty ( &tls->list ) );
370 ref_put ( &session->refcnt );
371
372 /* Free TLS structure itself */
373 zfree ( tls );
374}
unsigned long tmp
Definition linux_pci.h:65
#define list_for_each_entry_safe(pos, tmp, head, member)
Iterate over entries in a list, safe against deletion of the current entry.
Definition list.h:459
#define ref_put(refcnt)
Drop reference to object.
Definition refcnt.h:107
struct list_head list
List of which this buffer is a member.
Definition iobuf.h:105
struct tls_cipherspec pending
Next cipher specification.
Definition tls.h:319
struct private_key * key
Private key.
Definition tls.h:423
struct x509_chain * chain
Certificate chain (if any).
Definition tls.h:425
struct tls_server server
Server state.
Definition tls.h:485
struct tls_rx rx
Receive state.
Definition tls.h:481
struct tls_session_ticket new_ticket
New session ticket (if any).
Definition tls.h:456
struct tls_client client
Client state.
Definition tls.h:483
struct tls_cipherspec_pair cipherspec
Cipher specifications.
Definition tls.h:405
struct list_head data
List of received data buffers.
Definition tls.h:415
struct io_buffer * handshake
Received handshake fragment (if any).
Definition tls.h:417
struct x509_root * root
Root of trust.
Definition tls.h:433
struct x509_chain * chain
Certificate chain (if any).
Definition tls.h:435
struct refcnt refcnt
Reference counter.
Definition tls.h:366
static void tls_clear_digest(struct tls_connection *tls)
Clear key schedule digest algorithm.
Definition tls.c:457
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, tls_session_ticket::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_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 382 of file tls.c.

382 {
383
384 /* Remove pending operations, if applicable */
387 pending_put ( &tls->server.validation );
388
389 /* Remove process */
390 process_del ( &tls->tx.process );
391
392 /* Close all interfaces */
393 intf_shutdown ( &tls->cipherstream, rc );
394 intf_shutdown ( &tls->plainstream, rc );
395 intf_shutdown ( &tls->server.validator, rc );
396
397 /* Remove from session */
398 list_del ( &tls->list );
399 INIT_LIST_HEAD ( &tls->list );
400
401 /* Close secure channel */
402 channel_close ( &tls->channel );
403
404 /* Resume all other connections, in case we were the lead connection */
405 tls_tx_resume_all ( tls->session );
406}
void channel_close(struct secure_channel *channel)
Close secure channel.
Definition channel.c:1301
void intf_shutdown(struct interface *intf, int rc)
Shut down an object interface.
Definition interface.c:279
#define INIT_LIST_HEAD(list)
Initialise a list head.
Definition list.h:46
void pending_put(struct pending_operation *pending)
Mark an operation as no longer pending.
Definition pending.c:59
void process_del(struct process *process)
Remove process from process list.
Definition process.c:80
struct pending_operation negotiation
Security negotiation pending operation.
Definition tls.h:427
struct interface plainstream
Plaintext stream.
Definition tls.h:459
struct pending_operation validation
Certificate validation pending operation.
Definition tls.h:439
struct interface validator
Certificate validator.
Definition tls.h:437
struct pending_operation negotiation
Security negotiation pending operation.
Definition tls.h:441
struct process process
Transmit process.
Definition tls.h:399
static void tls_tx_resume_all(struct tls_session *session)
Resume TX state machine for all connections within a session.
Definition tls.c:1552

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

Referenced by tls_close_alert(), and tls_new_alert().

◆ tls_close_alert()

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

Send closure alert and finish with TLS connection.

Parameters
tlsTLS connection
rcStatus code

Definition at line 414 of file tls.c.

414 {
415
416 /* Send closure alert */
418
419 /* Close connection */
420 tls_close ( tls, rc );
421}
static int tls_send_alert(struct tls_connection *tls, unsigned int level, unsigned int description)
Transmit Alert record.
Definition tls.c:2140
static void tls_close(struct tls_connection *tls, int rc)
Finish with TLS connection.
Definition tls.c:382
#define TLS_ALERT_CLOSE_NOTIFY
Definition tls.h:86
#define TLS_ALERT_WARNING
Definition tls.h:82

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

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

◆ tls_nonce()

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

Generate deterministic connection nonce.

Parameters
tlsTLS connection
randomConnection nonce to fill in

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

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

Definition at line 443 of file tls.c.

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

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

Referenced by tls_client_hello(), and tls_set_digest().

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

474 {
475 const struct tls_key_schedule_operations *op;
476 struct tls_random nonce;
477 int rc;
478
479 /* Clear existing key schedule digest algorithm */
480 tls_clear_digest ( tls );
481
482 /* Select key schedule */
483 if ( tls_version ( tls, TLS_VERSION_TLS_1_2 ) ) {
484 op = &tlskey_hash;
485 } else {
487 }
488
489 /* Generate client random bytes */
490 tls_nonce ( tls, &nonce );
491
492 /* Start key schedule */
493 if ( ( rc = tlskey_start ( &tls->key, op, digest, &nonce ) ) != 0 ) {
494 DBGC ( tls, "TLS %p could not initialise key schedule: %s\n",
495 tls, strerror ( rc ) );
496 return rc;
497 }
498
499 return 0;
500}
static uint16_t struct vmbus_xfer_pages_operations * op
Definition netvsc.h:327
TLS key schedule operations.
Definition tlskey.h:170
TLS client or server random bytes.
Definition tlskey.h:36
static int tls_version(struct tls_connection *tls, unsigned int version)
Check for TLS version.
Definition tls.c:281
static void tls_nonce(struct tls_connection *tls, struct tls_random *nonce)
Generate deterministic connection nonce.
Definition tls.c:443
#define TLS_VERSION_TLS_1_2
TLS version 1.2.
Definition tls.h:48
int tlskey_start(struct tls_key_schedule *tlskey, const struct tls_key_schedule_operations *op, struct digest_algorithm *digest, const struct tls_random *nonce)
Start key schedule.
Definition tlskey.c:180
const struct tls_key_schedule_operations tlskey_hash
TLS key schedule based on P_Hash().
Definition tlskey.c:1819
const struct tls_key_schedule_operations tlskey_md5_sha1
TLS key schedule based on P_MD5()+P_SHA1().
Definition tlskey.c:1993

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

Referenced by tls_select_cipher().

◆ tls_cipher_name()

const char * tls_cipher_name ( struct tls_cipher_suite * suite)
static

Get cipher suite name (for debugging).

Parameters
suiteCipher suite
Return values
nameCipher suite name

Definition at line 527 of file tls.c.

527 {
529 struct pubkey_algorithm *pubkey = suite->pubkey;
530 struct cipher_algorithm *cipher = suite->cipher;
531 struct digest_algorithm *digest = suite->digest;
532 struct digest_algorithm *handshake = suite->handshake;
533 const char *exchange_name;
534 const char *pubkey_name;
535 const char *digest_name;
536 static char buf[64];
537
538 /* Strip uninteresting name components */
539 exchange_name = ( ( exchange == &tls_pubkey_exchange_algorithm ) ?
540 NULL : exchange->name );
541 pubkey_name = ( ( pubkey == &pubkey_null ) ? NULL : pubkey->name );
542 digest_name = ( ( digest == &digest_null ) ?
543 handshake->name : digest->name );
544
545 /* Construct name */
546 snprintf ( buf, sizeof ( buf ), "%s%s%s%s%s-%d-%s",
547 ( exchange_name ? exchange_name : "" ),
548 ( exchange_name ? "-" : "" ),
549 ( pubkey_name ? pubkey_name : "" ),
550 ( pubkey_name ? "-" : "" ),
551 cipher->name, ( suite->key_len * 8 ), digest_name );
552
553 return buf;
554}
struct pubkey_algorithm pubkey_null
struct digest_algorithm digest_null
Definition crypto_null.c:53
const char * name
Algorithm name.
Definition crypto.h:60
const char * name
Algorithm name.
Definition crypto.h:21
A public key algorithm.
Definition crypto.h:142
const char * name
Algorithm name.
Definition crypto.h:144
struct pubkey_algorithm * pubkey
Public-key encryption algorithm.
Definition tls.h:243
uint8_t key_len
Key length.
Definition tls.h:253
struct tls_key_exchange_algorithm * exchange
Key exchange algorithm.
Definition tls.h:241
struct digest_algorithm * handshake
Handshake digest algorithm (for TLSv1.2 and above).
Definition tls.h:249
A TLS key exchange algorithm.
Definition tls.h:210
const char * name
Algorithm name.
Definition tls.h:212
struct exchange_algorithm * exchange
Default key exchange algorithm.
Definition tls.h:214
struct tls_key_exchange_algorithm tls_pubkey_exchange_algorithm
Public key exchange algorithm.
Definition tls.c:873
int snprintf(char *buf, size_t size, const char *fmt,...)
Write a formatted string to a buffer.
Definition vsprintf.c:383

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

Referenced by tls_change_cipher(), and tls_select_cipher().

◆ tls_find_cipher_suite()

struct tls_cipher_suite * tls_find_cipher_suite ( unsigned int cipher_suite)
static

Identify cipher suite.

Parameters
cipher_suiteCipher suite specification
Return values
suiteCipher suite, or NULL

Definition at line 563 of file tls.c.

563 {
564 struct tls_cipher_suite *suite;
565
566 /* Identify cipher suite */
568 if ( suite->code == cipher_suite )
569 return suite;
570 }
571
572 return NULL;
573}
uint16_t code
Numeric code (in network-endian order).
Definition tls.h:251
#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:263

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 specification.

Parameters
cipherspecTLS cipher specification

Definition at line 580 of file tls.c.

581 {
582
583 zfree ( cipherspec->dynamic );
584 memset ( cipherspec, 0, sizeof ( *cipherspec ) );
585 cipherspec->suite = &tls_cipher_suite_null;
586}
void * dynamic
Dynamically-allocated storage.
Definition tls.h:303
struct tls_cipher_suite tls_cipher_suite_null
Null cipher suite.
Definition tls.c:510

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 specification.

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

Definition at line 596 of file tls.c.

598 {
599 size_t total;
600 void *dynamic;
601
602 /* Clear out old cipher contents, if any */
603 tls_clear_cipher ( tls, cipherspec );
604
605 /* Allocate dynamic storage */
606 total = ( suite->key_len + suite->mac_len + suite->fixed_iv_len );
607 dynamic = zalloc ( total );
608 if ( ! dynamic ) {
609 DBGC ( tls, "TLS %p could not allocate %zd bytes for crypto "
610 "context\n", tls, total );
611 return -ENOMEM_CONTEXT;
612 }
613
614 /* Assign storage */
615 cipherspec->dynamic = dynamic;
616 cipherspec->cipher_key = dynamic; dynamic += suite->key_len;
617 cipherspec->mac_secret = dynamic; dynamic += suite->mac_len;
618 cipherspec->fixed_iv = dynamic; dynamic += suite->fixed_iv_len;
619 assert ( ( cipherspec->dynamic + total ) == dynamic );
620
621 /* Store parameters */
622 cipherspec->suite = suite;
623
624 return 0;
625}
void * zalloc(size_t size)
Allocate cleared memory.
Definition malloc.c:718
void * cipher_key
Cipher key.
Definition tls.h:305
void * mac_secret
MAC secret.
Definition tls.h:307
#define ENOMEM_CONTEXT
Definition tls.c:121

References assert, tls_cipherspec::cipher_key, DBGC, tls_cipherspec::dynamic, ENOMEM_CONTEXT, tls_cipherspec::fixed_iv, tls_cipher_suite::fixed_iv_len, tls_cipher_suite::key_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 cipher suite.

Parameters
tlsTLS connection
cipher_suiteCipher suite specification
Return values
rcReturn status code

Definition at line 634 of file tls.c.

635 {
636 struct tls_cipher_suite *suite;
637 struct digest_algorithm *digest;
638 int rc;
639
640 /* Identify cipher suite */
641 suite = tls_find_cipher_suite ( cipher_suite );
642 if ( ! suite ) {
643 DBGC ( tls, "TLS %p does not support cipher suite %#04x\n",
644 tls, ntohs ( cipher_suite ) );
645 return -ENOTSUP_CIPHER;
646 }
647
648 /* Sanity checks */
649 if ( ! ( suite->exchange && suite->pubkey && suite->cipher &&
650 suite->digest && suite->handshake ) ) {
651 DBGC ( tls, "TLS %p cannot use broken cipher suite %#04x\n",
652 tls, ntohs ( cipher_suite ) );
653 return -ENOTSUP_CIPHER;
654 }
655
656 /* Set (or clear) key exchange algorithm */
657 tls->exchange = suite->exchange->exchange;
658
659 /* Set key schedule digest algorithm */
660 digest = ( tls_version ( tls, TLS_VERSION_TLS_1_2 ) ?
661 suite->handshake : &md5_sha1_algorithm );
662 if ( ( rc = tls_set_digest ( tls, digest ) ) != 0 )
663 return rc;
664
665 /* Set ciphers */
666 if ( ( rc = tls_set_cipher ( tls, &tls->tx.cipherspec.pending,
667 suite ) ) != 0 )
668 return rc;
669 if ( ( rc = tls_set_cipher ( tls, &tls->rx.cipherspec.pending,
670 suite ) ) != 0 )
671 return rc;
672 DBGC ( tls, "TLS %p selected cipher suite %s\n",
673 tls, tls_cipher_name ( suite ) );
674
675 return 0;
676}
#define ntohs(value)
Definition byteswap.h:137
struct digest_algorithm md5_sha1_algorithm
Hybrid MD5+SHA1 digest algorithm.
Definition md5_sha1.c:84
struct exchange_algorithm * exchange
Key exchange algorithm.
Definition tls.h:466
#define ENOTSUP_CIPHER
Definition tls.c:149
static int tls_set_digest(struct tls_connection *tls, struct digest_algorithm *digest)
Set key schedule digest algorithm.
Definition tls.c:473
static int tls_set_cipher(struct tls_connection *tls, struct tls_cipherspec *cipherspec, struct tls_cipher_suite *suite)
Set cipher specification.
Definition tls.c:596
static struct tls_cipher_suite * tls_find_cipher_suite(unsigned int cipher_suite)
Identify cipher suite.
Definition tls.c:563
static const char * tls_cipher_name(struct tls_cipher_suite *suite)
Get cipher suite name (for debugging).
Definition tls.c:527

References tls_cipher_suite::cipher, tls_rx::cipherspec, tls_tx::cipherspec, DBGC, tls_cipher_suite::digest, ENOTSUP_CIPHER, tls_cipher_suite::exchange, tls_connection::exchange, tls_key_exchange_algorithm::exchange, tls_cipher_suite::handshake, md5_sha1_algorithm, ntohs, tls_cipherspec_pair::pending, tls_cipher_suite::pubkey, rc, tls_connection::rx, tls_cipher_name(), 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,
struct secure_pipe * pipe )
static

Activate next cipher suite.

Parameters
tlsTLS connection
pairCipher specification pair
pipeSecure pipe
Return values
rcReturn status code

Definition at line 686 of file tls.c.

688 {
689 struct tls_cipherspec *pending = &pair->pending;
690 struct tls_cipherspec *active = &pair->active;
691 struct tls_cipher_suite *suite = pending->suite;
692 size_t mac_len = suite->mac_len;
693 size_t key_len = suite->key_len;
694 size_t iv_len = suite->fixed_iv_len;
695 int rc;
696
697 /* Sanity check */
698 if ( suite == &tls_cipher_suite_null ) {
699 DBGC ( tls, "TLS %p refusing to use null %s cipher\n",
700 tls, tls_pipe_name ( tls, pipe ) );
701 return -ENOTSUP_NULL;
702 }
703
704 /* Generate traffic secret */
705 if ( ( rc = tlskey_traffic ( &tls->key, pair->writer,
706 &tls_application ) ) != 0 ) {
707 DBGC ( tls, "TLS %p could not generate %s %s traffic secret: "
708 "%s\n", tls, tls_pipe_name ( tls, pipe ),
709 pair->writer->name, strerror ( rc ) );
710 return rc;
711 }
712
713 /* Generate cipher key material */
714 if ( ( rc = tlskey_cipher ( &tls->key, pair->writer,
715 pending->cipher_key, key_len,
716 pending->fixed_iv, iv_len,
717 pending->mac_secret, mac_len ) ) != 0 ) {
718 DBGC ( tls, "TLS %p could not generate %s %s keys: %s\n",
719 tls, tls_pipe_name ( tls, pipe ), pair->writer->name,
720 strerror ( rc ) );
721 return rc;
722 }
723
724 /* Set cipher algorithm and key */
725 if ( ( rc = channel_set_cipher ( &tls->channel, pipe, suite->cipher,
726 pending->cipher_key,
727 key_len ) ) != 0 ) {
728 DBGC ( tls, "TLS %p could not set %s cipher: %s\n",
729 tls, tls_pipe_name ( tls, pipe ), strerror ( rc ) );
730 return rc;
731 }
732
733 /* Swap in new cipher suite */
734 tls_clear_cipher ( tls, active );
735 memswap ( active, pending, sizeof ( *active ) );
736 DBGC ( tls, "TLS %p activated %s cipher %s\n",
737 tls, tls_pipe_name ( tls, pipe ), tls_cipher_name ( suite ) );
738
739 return 0;
740}
int channel_set_cipher(struct secure_channel *channel, struct secure_pipe *pipe, struct cipher_algorithm *cipher, const void *key, size_t len)
Set cipher algorithm and key.
Definition channel.c:1136
uint32_t pending
Pending events.
Definition hyperv.h:1
void * memswap(void *first, void *second, size_t len)
Swap memory regions.
Definition string.c:154
const struct tls_endpoint * writer
Writer endpoint.
Definition tls.h:315
const char name[7]
Name (for key expansion labels).
Definition tlskey.h:23
static const char * tls_pipe_name(struct tls_connection *tls, struct secure_pipe *pipe)
Get pipe name (for debugging).
Definition tls.c:293
#define ENOTSUP_NULL
Definition tls.c:153
int tlskey_cipher(struct tls_key_schedule *tlskey, const struct tls_endpoint *writer, void *key, size_t key_len, void *iv, size_t iv_len, void *mac, size_t mac_len)
Generate cipher key material.
Definition tlskey.c:691
int tlskey_traffic(struct tls_key_schedule *tlskey, const struct tls_endpoint *writer, const struct tls_phase *phase)
Generate traffic secret.
Definition tlskey.c:639
const struct tls_phase tls_application
Application traffic phase.
Definition tlskey.c:151

References tls_cipherspec_pair::active, tls_connection::channel, channel_set_cipher(), tls_cipher_suite::cipher, DBGC, ENOTSUP_NULL, tls_cipher_suite::fixed_iv_len, tls_connection::key, tls_cipher_suite::key_len, tls_cipher_suite::mac_len, memswap(), tls_endpoint::name, pending, tls_cipherspec_pair::pending, rc, strerror(), tls_application, tls_cipher_name(), tls_cipher_suite_null, tls_clear_cipher(), tls_pipe_name(), tlskey_cipher(), tlskey_traffic(), and tls_cipherspec_pair::writer.

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

762 {
763 struct tls_signature_hash_algorithm *sig_hash;
764
765 /* Identify signature and hash algorithm */
767 if ( ( sig_hash->pubkey == pubkey ) &&
768 ( sig_hash->digest == digest ) ) {
769 return sig_hash;
770 }
771 }
772
773 return NULL;
774}
A TLS signature algorithm.
Definition tls.h:323
struct pubkey_algorithm * pubkey
Public-key algorithm.
Definition tls.h:327
struct digest_algorithm * digest
Digest algorithm.
Definition tls.h:325
#define TLS_SIG_HASH_ALGORITHMS
TLS signature hash algorithm table.
Definition tls.h:339

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

783 {
784 struct tls_signature_hash_algorithm *sig_hash;
785
786 /* Identify signature and hash algorithm */
788 if ( sig_hash->code == code )
789 return sig_hash;
790 }
791
792 return NULL;
793}
static unsigned int code
Definition hyperv.h:26
uint16_t code
Numeric code (in network-endian order).
Definition tls.h:331

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

Referenced by tls_new_server_key_exchange().

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

809 {
810 struct tls_named_group *group;
811
812 /* Identify named group */
814 if ( group->code && ( group->code == named_group ) )
815 return group;
816 }
817
818 return NULL;
819}
uint16_t group
Type of event.
Definition ena.h:1
A TLS named group.
Definition tls.h:274
#define TLS_NAMED_GROUPS
TLS named group table.
Definition tls.h:282

References for_each_table_entry, group, NULL, and TLS_NAMED_GROUPS.

Referenced by tls_parse_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 831 of file tls.c.

832 {
833 struct tls_named_group *group;
834
835 /* Identify named group by parameters */
837 if ( is_ffdhe ( group->exchange ) &&
838 ffdhe_has_params ( group->exchange, dh_p, dh_p_len,
839 dh_g, dh_g_len ) ) {
840 return group;
841 }
842 }
843
844 return NULL;
845}
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_parse_dhe().

◆ tls_parse_null()

int tls_parse_null ( struct tls_connection * tls,
const void * data,
size_t len,
struct tls_key_exchange_parameters *params __unused )
static

Parse key exchange parameters from unexpected Server Key Exchange record.

Parameters
dataServer Key Exchange handshake record
lenLength of Server Key Exchange handshake record
paramsKey exchange parameters to fill in
Return values
rcReturn status code

Definition at line 856 of file tls.c.

857 {
858
859 DBGC ( tls, "TLS %p received unexpected ServerKeyExchange:\n", tls );
860 DBGC_HDA ( tls, 0, data, len );
861 return -EINVAL_KEY_EXCHANGE;
862}
#define DBGC_HDA(...)
Definition compiler.h:531
#define EINVAL_KEY_EXCHANGE
Definition tls.c:105

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

◆ tls_parse_dhe()

int tls_parse_dhe ( struct tls_connection * tls,
const void * data,
size_t len,
struct tls_key_exchange_parameters * params )
static

Parse key exchange parameters from DHE Server Key Exchange record.

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

Definition at line 889 of file tls.c.

891 {
892 struct tls_named_group *group;
893 const struct {
895 uint8_t data[0];
896 } __attribute__ (( packed )) *dh_val[3];
897 typeof ( dh_val[0] ) dh_p;
898 typeof ( dh_val[1] ) dh_g;
899 typeof ( dh_val[2] ) dh_ys;
900 const void *param;
901 size_t remaining;
902 size_t frag_len;
903 unsigned int i;
904
905 /* Parse ServerKeyExchange */
906 param = data;
907 remaining = len;
908 for ( i = 0 ; i < ( sizeof ( dh_val ) / sizeof ( dh_val[0] ) ) ; i++ ){
909 dh_val[i] = param;
910 if ( ( sizeof ( *dh_val[i] ) > remaining ) ||
911 ( ntohs ( dh_val[i]->len ) > ( remaining -
912 sizeof ( *dh_val[i] ) ) )){
913 DBGC ( tls, "TLS %p received underlength "
914 "ServerKeyExchange\n", tls );
915 DBGC_HDA ( tls, 0, data, len );
916 return -EINVAL_KEY_EXCHANGE;
917 }
918 frag_len = ( sizeof ( *dh_val[i] ) + ntohs ( dh_val[i]->len ));
919 param += frag_len;
920 remaining -= frag_len;
921 }
922 params->len = ( len - remaining );
923
924 /* Identify named group and partner key */
925 dh_p = dh_val[0];
926 dh_g = dh_val[1];
927 dh_ys = dh_val[2];
928 group = tls_find_param_group ( dh_p->data, ntohs ( dh_p->len ),
929 dh_g->data, ntohs ( dh_g->len ) );
930 if ( ! group ) {
931 DBGC ( tls, "TLS %p unsupported %d-bit group:\n",
932 tls, ( 8 * ntohs ( dh_p->len ) ) );
933 DBGC_HDA ( tls, 0, data, len );
934 return -ENOTSUP_GROUP;
935 }
936 params->exchange = group->exchange;
937 params->partner = dh_ys->data;
938 params->partner_len = ntohs ( dh_ys->len );
939
940 return 0;
941}
typeof(acpi_finder=acpi_find)
ACPI table finder.
Definition acpi.c:48
unsigned short uint16_t
Definition stdint.h:11
struct hv_monitor_parameter param[4][32]
Parameters.
Definition hyperv.h:13
struct exchange_algorithm * exchange
Key exchange algorithm.
Definition tls.h:202
size_t len
Length of parameters (excluding trailing signature).
Definition tls.h:200
size_t partner_len
Length of partner key.
Definition tls.h:206
const void * partner
Partner key.
Definition tls.h:204
#define ENOTSUP_GROUP
Definition tls.c:165
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:831

References __attribute__, data, DBGC, DBGC_HDA, EINVAL_KEY_EXCHANGE, ENOTSUP_GROUP, tls_key_exchange_parameters::exchange, group, len, tls_key_exchange_parameters::len, ntohs, param, tls_key_exchange_parameters::partner, tls_key_exchange_parameters::partner_len, tls_find_param_group(), and typeof().

◆ tls_parse_ecdhe()

int tls_parse_ecdhe ( struct tls_connection * tls,
const void * data,
size_t len,
struct tls_key_exchange_parameters * params )
static

Parse key exchange parameters from ECDHE Server Key Exchange record.

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

Definition at line 960 of file tls.c.

962 {
963 struct tls_named_group *group;
964 const struct {
965 uint8_t curve_type;
966 uint16_t named_group;
967 uint8_t public_len;
968 uint8_t public[0];
969 } __attribute__ (( packed )) *ecdh = data;
970
971 /* Parse ServerKeyExchange record */
972 if ( ( sizeof ( *ecdh ) > len ) ||
973 ( ecdh->public_len > ( len - sizeof ( *ecdh ) ) ) ) {
974 DBGC ( tls, "TLS %p received underlength ServerKeyExchange\n",
975 tls );
976 DBGC_HDA ( tls, 0, data, len );
977 return -EINVAL_KEY_EXCHANGE;
978 }
979 params->len = ( sizeof ( *ecdh ) + ecdh->public_len );
980
981 /* Identify named group and partner key */
982 if ( ecdh->curve_type != TLS_NAMED_CURVE_TYPE ) {
983 DBGC ( tls, "TLS %p unsupported curve type %d\n",
984 tls, ecdh->curve_type );
985 DBGC_HDA ( tls, 0, data, len );
986 return -ENOTSUP_GROUP;
987 }
988 group = tls_find_named_group ( ecdh->named_group );
989 if ( ! group ) {
990 DBGC ( tls, "TLS %p unsupported named group %d\n",
991 tls, ntohs ( ecdh->named_group ) );
992 DBGC_HDA ( tls, 0, data, len );
993 return -ENOTSUP_GROUP;
994 }
995 params->exchange = group->exchange;
996 params->partner = ecdh->public;
997 params->partner_len = ecdh->public_len;
998
999 return 0;
1000}
static struct tls_named_group * tls_find_named_group(unsigned int named_group)
Identify named key exchange group.
Definition tls.c:809
#define TLS_NAMED_CURVE_TYPE
TLS named curve type.
Definition tls.h:271

References __attribute__, data, DBGC, DBGC_HDA, EINVAL_KEY_EXCHANGE, ENOTSUP_GROUP, tls_key_exchange_parameters::exchange, group, len, tls_key_exchange_parameters::len, ntohs, tls_key_exchange_parameters::partner, tls_key_exchange_parameters::partner_len, tls_find_named_group(), and TLS_NAMED_CURVE_TYPE.

◆ tls_keysize_is_variable()

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

Check if key exchange keys have a variable size.

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

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

Definition at line 1022 of file tls.c.

1023 {
1024
1025 /* TLS versions 1.3 and later always have fixed-size keys */
1026 if ( tls_version ( tls, TLS_VERSION_TLS_1_3 ) )
1027 return 0;
1028
1029 /* TLS versions 1.2 and earlier have variable-sized FFDHE keys */
1030 return is_ffdhe ( exchange );
1031}
#define TLS_VERSION_TLS_1_3
TLS version 1.3.
Definition tls.h:51

References tls_key_exchange_algorithm::exchange, is_ffdhe(), tls_version(), and TLS_VERSION_TLS_1_3.

Referenced by tls_channel_apply(), and tls_key_agree().

◆ tls_key_share()

int tls_key_share ( struct tls_connection * tls,
struct exchange_algorithm * exchange,
void * public,
size_t len )
static

Share public key.

Parameters
tlsTLS connection
exchangeKey exchange algorithm
publicPublic key to fill in
lenLength of public key
Return values
rcReturn status code

Definition at line 1049 of file tls.c.

1051 {
1052 struct secure_channel *channel = &tls->channel;
1053 size_t pubsize = exchange->pubsize;
1054 int rc;
1055
1056 /* Check key length */
1057 if ( pubsize != len ) {
1058 DBGC ( tls, "TLS %p wrong public %s key size (%zd bytes)\n",
1059 tls, exchange->name, len );
1060 return -EINVAL_KEY_EXCHANGE;
1061 }
1062
1063 /* Share public key */
1064 if ( ( rc = channel_key_share ( channel, exchange, public ) ) != 0 ) {
1065 DBGC ( tls, "TLS %p could not share public %s key: %s\n",
1066 tls, exchange->name, strerror ( rc ) );
1067 return rc;
1068 }
1069
1070 return 0;
1071}
int channel_key_share(struct secure_channel *channel, struct exchange_algorithm *exchange, void *public)
Share public key.
Definition channel.c:320
uint32_t channel
RNDIS channel.
Definition netvsc.h:3
size_t pubsize
Public key size.
Definition crypto.h:216
const char * name
Algorithm name.
Definition crypto.h:212
A secure channel.
Definition channel.h:72

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

Referenced by tls_key_build().

◆ tls_key_agree()

int tls_key_agree ( struct tls_connection * tls,
struct exchange_algorithm * exchange,
const void * partner,
size_t len )
static

Agree shared secret.

Parameters
tlsTLS connection
exchangeKey exchange algorithm
partnerPartner public key
lenLength of partner public key
Return values
rcReturn status code

Definition at line 1082 of file tls.c.

1084 {
1085 struct secure_channel *channel = &tls->channel;
1086 size_t pubsize = exchange->pubsize;
1087 uint8_t *tmp;
1088 size_t pad_len;
1089 int strip;
1090 int rc;
1091
1092 /* Allocate space for potentially padded partner key */
1093 tmp = zalloc ( pubsize );
1094 if ( ! tmp ) {
1095 rc = -ENOMEM;
1096 goto err_alloc;
1097 }
1098
1099 /* Validate partner key */
1100 if ( len > pubsize ) {
1101 DBGC ( tls, "TLS %p overlength partner %s key:\n",
1102 tls, exchange->name );
1103 DBGC_HDA ( tls, 0, partner, len );
1105 goto err_len;
1106 }
1107
1108 /* TLSv1.2 and earlier may require zero-padding for FFDHE keys */
1109 strip = tls_keysize_is_variable ( tls, exchange );
1110 pad_len = ( pubsize - len );
1111 if ( pad_len && ( ! strip ) ) {
1112 DBGC ( tls, "TLS %p underlength partner %s key:\n",
1113 tls, exchange->name );
1114 DBGC_HDA ( tls, 0, partner, len );
1116 goto err_pad;
1117 }
1118 memcpy ( ( tmp + pad_len ), partner, len );
1119
1120 /* Agree shared secret */
1121 if ( ( rc = channel_key_agree ( channel, exchange, tmp ) ) != 0 ) {
1122 DBGC ( tls, "TLS %p could not agree shared %s key: %s\n",
1123 tls, exchange->name, strerror ( rc ) );
1124 goto err_agree;
1125 }
1126
1127 err_agree:
1128 err_pad:
1129 err_len:
1130 zfree ( tmp );
1131 err_alloc:
1132 return rc;
1133}
int channel_key_agree(struct secure_channel *channel, struct exchange_algorithm *exchange, const void *partner)
Agree shared secret.
Definition channel.c:424
struct eth_slow_lacp_entity_tlv partner
Partner information.
Definition eth_slow.h:5
#define ENOMEM
Not enough space.
Definition errno.h:578
static int tls_keysize_is_variable(struct tls_connection *tls, struct exchange_algorithm *exchange)
Check if key exchange keys have a variable size.
Definition tls.c:1022

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

Referenced by tls_new_server_key_exchange().

◆ tls_key_encrypt()

int tls_key_encrypt ( struct tls_connection * tls,
struct exchange_algorithm * exchange,
struct asn1_builder * builder )
static

Encrypt (and implicitly bind) shared secret.

Parameters
tlsTLS connection
exchangeKey exchange algorithm
builderASN.1 builder
Return values
rcReturn status code

Definition at line 1143 of file tls.c.

1145 {
1146 struct secure_channel *channel = &tls->channel;
1147 struct x509_certificate *cert;
1148 struct pubkey_algorithm *pubkey;
1149 int rc;
1150
1151 /* Identify server certificate */
1152 if ( ! tls->server.chain ) {
1153 DBGC ( tls, "TLS %p has no server certificate chain\n", tls );
1154 return -ENOENT_CERT;
1155 }
1156 cert = x509_first ( tls->server.chain );
1157 if ( ! cert ) {
1158 DBGC ( tls, "TLS %p has no server certificate\n", tls );
1159 return -ENOENT_CERT;
1160 }
1161 pubkey = cert->subject.public_key.algorithm->pubkey;
1162
1163 /* Encrypt (and implicitly bind) shared secret */
1164 if ( ( rc = channel_bind_encrypt ( channel, cert, exchange, pubkey,
1165 builder ) ) != 0 ) {
1166 DBGC ( tls, "TLS %p could not encrypt %s key: %s\n",
1167 tls, exchange->name, strerror ( rc ) );
1168 return rc;
1169 }
1170
1171 return 0;
1172}
int channel_bind_encrypt(struct secure_channel *channel, struct x509_certificate *identity, struct exchange_algorithm *exchange, struct pubkey_algorithm *pubkey, struct asn1_builder *ciphertext)
Bind peer identity via shared secret encryption.
Definition channel.c:648
struct pubkey_algorithm * pubkey
Public-key algorithm (if applicable).
Definition asn1.h:435
An X.509 certificate.
Definition x509.h:216
struct x509_subject subject
Subject.
Definition x509.h:245
struct asn1_algorithm * algorithm
Public key algorithm.
Definition x509.h:54
struct x509_public_key public_key
Public key information.
Definition x509.h:66
#define ENOENT_CERT
Definition tls.c:113
static struct x509_certificate * x509_first(struct x509_chain *chain)
Get first certificate in X.509 certificate chain.
Definition x509.h:311

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

Referenced by tls_key_build().

◆ tls_key_build()

int tls_key_build ( struct tls_connection * tls,
struct exchange_algorithm * exchange,
struct asn1_builder * builder )
static

Build shareable key.

Parameters
tlsTLS connection
exchangeKey exchange algorithm
builderASN.1 builder
Return values
rcReturn status code

Definition at line 1182 of file tls.c.

1184 {
1185 size_t pubsize = exchange->pubsize;
1186 int rc;
1187
1188 /* Share or encrypt as applicable */
1189 if ( pubsize ) {
1190
1191 /* Allocate space for public key */
1192 if ( ( rc = asn1_grow ( builder, pubsize ) ) != 0 )
1193 return rc;
1194
1195 /* Share public key */
1196 if ( ( rc = tls_key_share ( tls, exchange, builder->data,
1197 pubsize ) ) != 0 ) {
1198 return rc;
1199 }
1200
1201 } else {
1202
1203 /* Encrypt (and implicitly bind) shared secret */
1204 if ( ( rc = tls_key_encrypt ( tls, exchange,
1205 builder ) ) != 0 ) {
1206 return rc;
1207 }
1208 }
1209
1210 return 0;
1211}
int asn1_grow(struct asn1_builder *builder, size_t extra)
Grow ASN.1 builder.
Definition asn1.c:1036
void * data
Data.
Definition asn1.h:36
static int tls_key_share(struct tls_connection *tls, struct exchange_algorithm *exchange, void *public, size_t len)
Share public key.
Definition tls.c:1049
static int tls_key_encrypt(struct tls_connection *tls, struct exchange_algorithm *exchange, struct asn1_builder *builder)
Encrypt (and implicitly bind) shared secret.
Definition tls.c:1143

References asn1_grow(), asn1_builder::data, exchange_algorithm::pubsize, rc, tls_key_encrypt(), and tls_key_share().

Referenced by tls_send_client_key_exchange().

◆ tls_channel_reset()

void tls_channel_reset ( struct secure_channel * channel)
static

Reset the key schedule.

Parameters
channelSecure channel

Definition at line 1225 of file tls.c.

1225 {
1226 struct tls_connection *tls =
1228
1229 /* Reset key schedule */
1230 tlskey_reset ( &tls->key );
1231}
void tlskey_reset(struct tls_key_schedule *tlskey)
Reset key schedule.
Definition tlskey.c:492

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

◆ tls_channel_apply()

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

Apply a new shared secret to key schedule.

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

Definition at line 1242 of file tls.c.

1244 {
1245 struct tls_connection *tls =
1247 size_t shared_len = exchange->sharedsize;
1248 int rc;
1249
1250 /* Strip leading zeros if needed */
1251 if ( tls_keysize_is_variable ( tls, exchange ) ) {
1252 /* TLS v1.2 and earlier strip leading zeros for FFDHE
1253 *
1254 * This code can be reached only with the result from
1255 * a successful FFDHE key exchange, and so the shared
1256 * secret cannot ever end up as all zeros.
1257 */
1258 while ( shared_len && ( ! *( ( const uint8_t * ) shared ) ) ) {
1259 shared++;
1260 shared_len--;
1261 }
1262 assert ( shared_len > 0 );
1263 }
1264 DBGC ( tls, "TLS %p shared (pre-master) secret:\n", tls );
1265 DBGC_HDA ( tls, 0, shared, shared_len );
1266
1267 /* Apply shared secret to key schedule */
1268 if ( ( rc = tlskey_apply ( &tls->key, shared, shared_len ) ) != 0 ) {
1269 DBGC ( tls, "TLS %p could not apply shared secret: %s\n",
1270 tls, strerror ( rc ) );
1271 return rc;
1272 }
1273
1274 /* Set accumulation flag if applicable */
1275 *accumulated = tlskey_is_accumulating ( &tls->key );
1276
1277 return 0;
1278}
size_t sharedsize
Shared secret size.
Definition crypto.h:218
int tlskey_apply(struct tls_key_schedule *tlskey, const void *shared, size_t shared_len)
Apply a new shared secret.
Definition tlskey.c:522
static int tlskey_is_accumulating(struct tls_key_schedule *tlskey)
Check if key schedule accumulates shared secrets.
Definition tlskey.h:329

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

◆ tls_channel_save()

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

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

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

Definition at line 1287 of file tls.c.

1288 {
1289 struct tls_connection *tls =
1291 struct tls_session *session =
1292 container_of ( psid, struct tls_session, psid );
1293 int rc;
1294
1295 /* We support saving pre-shared keys only once the secure
1296 * channel has been established (since resumed connections
1297 * will not receive a certificate chain and so will have no
1298 * further opportunities to validate the bound identity).
1299 */
1300 if ( ! channel_is_established ( channel ) ) {
1301 DBGC ( tls, "TLS %p cannot save pre-shared key before "
1302 "channel is established\n", tls );
1303 return -EPERM_SAVE;
1304 }
1305
1306 /* Save key material */
1307 if ( ( rc = tlskey_save ( &tls->key, NULL, 0,
1308 &session->psk ) ) != 0 ) {
1309 DBGC ( tls, "TLS %p could not save key material: %s\n",
1310 tls, strerror ( rc ) );
1311 return rc;
1312 }
1313
1314 return 0;
1315}
struct tls_preshared_key psk
Pre-shared key.
Definition tls.h:380
#define EPERM_SAVE
Definition tls.c:189
int tlskey_save(struct tls_key_schedule *tlskey, const void *nonce, size_t nonce_len, struct tls_preshared_key *psk)
Save pre-shared key.
Definition tlskey.c:785

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

◆ tls_channel_load()

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

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

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

Definition at line 1324 of file tls.c.

1325 {
1326 struct tls_connection *tls =
1328 struct tls_session *session =
1329 container_of ( psid, struct tls_session, psid );
1330 int rc;
1331
1332 /* Load key material */
1333 if ( ( rc = tlskey_load ( &tls->key, tls->extended_master_secret,
1334 &session->psk ) ) != 0 ) {
1335 DBGC ( tls, "TLS %p could not load key material: %s\n",
1336 tls, strerror ( rc ) );
1337 return rc;
1338 }
1339
1340 return 0;
1341}
int extended_master_secret
Extended master secret flag.
Definition tls.h:470
int tlskey_load(struct tls_key_schedule *tlskey, int ems, const struct tls_preshared_key *psk)
Load pre-shared key.
Definition tlskey.c:828

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

◆ tls_channel_verify()

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

Verify authenticator value.

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

Definition at line 1351 of file tls.c.

1352 {
1353 struct tls_connection *tls =
1355 int rc;
1356
1357 /* Sanity checks */
1358 if ( len != sizeof ( tls->verify.server ) ) {
1359 DBGC ( tls, "TLS %p invalid authenticator value:\n", tls );
1360 DBGC_HDA ( tls, 0, auth, len );
1361 return -EPERM_VERIFY;
1362 }
1363
1364 /* Generate verification data */
1365 if ( ( rc = tlskey_verify ( &tls->key, &tls_server,
1366 tls->verify.server,
1367 sizeof ( tls->verify.server ) ) ) != 0 ) {
1368 DBGC ( tls, "TLS %p could not generate server verification: "
1369 "%s\n", tls, strerror ( rc ) );
1370 return rc;
1371 }
1372
1373 /* Verify data */
1374 if ( memcmp ( tls->verify.server, auth, len ) != 0 ) {
1375 DBGC ( tls, "TLS %p incorrect authenticator value:\n", tls );
1376 return -EPERM_VERIFY;
1377 }
1378
1379 return 0;
1380}
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition string.c:115
struct tls_verify_data verify
Verification data.
Definition tls.h:472
TLS server state.
Definition tls.h:431
uint8_t server[12]
Server verification data.
Definition tls.h:178
#define EPERM_VERIFY
Definition tls.c:173
int tlskey_verify(struct tls_key_schedule *tlskey, const struct tls_endpoint *end, void *verify, size_t verify_len)
Generate verification data.
Definition tlskey.c:602

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

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

1405 {
1406 static const char label[] = "tls session id";
1407 struct tls_session *session;
1408 char *name_copy;
1409 int rc;
1410
1411 /* Find existing matching session, if any */
1412 list_for_each_entry ( session, &tls_sessions, list ) {
1413 if ( ( strcmp ( name, session->name ) == 0 ) &&
1414 ( tls->server.root == session->root ) &&
1415 ( tls->client.key == session->key ) ) {
1416 ref_get ( &session->refcnt );
1417 tls->session = session;
1418 DBGC ( tls, "TLS %p joining session %s\n", tls, name );
1419 return 0;
1420 }
1421 }
1422
1423 /* Create new session */
1424 session = zalloc ( sizeof ( *session ) + strlen ( name )
1425 + 1 /* NUL */ );
1426 if ( ! session ) {
1427 rc = -ENOMEM;
1428 goto err_alloc;
1429 }
1430 ref_init ( &session->refcnt, free_tls_session );
1431 name_copy = ( ( ( void * ) session ) + sizeof ( *session ) );
1432 strcpy ( name_copy, name );
1433 session->name = name_copy;
1434 session->root = x509_root_get ( tls->server.root );
1435 session->key = privkey_get ( tls->client.key );
1436 INIT_LIST_HEAD ( &session->conn );
1437 list_add ( &session->list, &tls_sessions );
1438
1439 /* Generate random initial session ID */
1440 channel_ephemeral_label ( &tls->channel, label, session->id.data,
1441 sizeof ( session->id.data ) );
1442 session->id.len = sizeof ( session->id.data );
1443
1444 /* Record session */
1445 tls->session = session;
1446
1447 DBGC ( tls, "TLS %p created session %s\n", tls, name );
1448 return 0;
1449
1450 ref_put ( &session->refcnt );
1451 err_alloc:
1452 return rc;
1453}
const char * name
Definition ath9k_hw.c:1986
#define list_add(new, head)
Add a new entry to the head of a list.
Definition list.h:70
static struct private_key * privkey_get(struct private_key *key)
Get reference to private key.
Definition privkey.h:31
#define ref_get(refcnt)
Get additional reference to object.
Definition refcnt.h:93
#define ref_init(refcnt, free)
Initialise a reference counter.
Definition refcnt.h:65
int strcmp(const char *first, const char *second)
Compare strings.
Definition string.c:174
char * strcpy(char *dest, const char *src)
Copy string.
Definition string.c:378
size_t strlen(const char *src)
Get length of string.
Definition string.c:244
uint8_t len
Length of ID.
Definition tls.h:352
uint8_t data[32]
ID.
Definition tls.h:350
const char * name
Server name.
Definition tls.h:371
struct tls_session_id id
Session ID.
Definition tls.h:382
static void free_tls_session(struct refcnt *refcnt)
Free TLS session.
Definition tls.c:317
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::channel, channel_ephemeral_label(), tls_connection::client, tls_session::conn, tls_session_id::data, DBGC, ENOMEM, free_tls_session(), tls_session::id, INIT_LIST_HEAD, tls_client::key, tls_session::key, tls_session_id::len, tls_session::list, list_add, list_for_each_entry, name, tls_session::name, privkey_get(), rc, ref_get, ref_init, ref_put, tls_session::refcnt, tls_server::root, tls_session::root, tls_connection::server, tls_connection::session, strcmp(), strcpy(), strlen(), x509_root_get(), and zalloc().

◆ tls_save()

int tls_save ( struct tls_connection * tls)
static

Save session for future resumption.

Parameters
tlsTLS connection
Return values
rcReturn status code

Definition at line 1461 of file tls.c.

1461 {
1462 struct tls_session *session = tls->session;
1463 int rc;
1464
1465 /* Save pre-shared key and peer identity */
1466 if ( ( rc = channel_save ( &tls->channel, &session->psid ) ) != 0 ) {
1467 DBGC ( tls, "TLS %p could not save: %s\n",
1468 tls, strerror ( rc ) );
1469 return rc;
1470 }
1471
1472 /* Record new session ID, if provided */
1473 if ( tls->new_id.len ) {
1474 memcpy ( &session->id, &tls->new_id, sizeof ( session->id ) );
1475 DBGC ( tls, "TLS %p saved session ID:\n", tls );
1476 DBGC_HDA ( tls, 0, session->id.data, session->id.len );
1477 }
1478
1479 /* Record (and consume) new session ticket, if provided */
1480 if ( tls->new_ticket.len ) {
1481 zfree ( session->ticket.data );
1482 session->ticket.data = tls->new_ticket.data;
1483 session->ticket.len = tls->new_ticket.len;
1484 tls->new_ticket.data = NULL;
1485 tls->new_ticket.len = 0;
1486 }
1487
1488 return 0;
1489}
int channel_save(struct secure_channel *channel, struct secure_preshared_identity *psid)
Save a pre-shared key.
Definition channel.c:738
struct tls_session_id new_id
New session ID (if any).
Definition tls.h:454
size_t len
Length of ticket data.
Definition tls.h:360

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

Referenced by tls_establish().

◆ tls_resume()

int tls_resume ( struct tls_connection * tls)
static

Resume session.

Parameters
tlsTLS connection
Return values
rcReturn status code

Definition at line 1497 of file tls.c.

1497 {
1498 struct tls_session *session = tls->session;
1499 int rc;
1500
1501 DBGC ( tls, "TLS %p resuming session ID:\n", tls );
1502 DBGC_HDA ( tls, 0, session->id.data, session->id.len );
1503
1504 /* Load pre-shared key and peer identity */
1505 if ( ( rc = channel_load ( &tls->channel, &session->psid ) ) != 0 ) {
1506 DBGC ( tls, "TLS %p could not resume: %s\n",
1507 tls, strerror ( rc ) );
1508 return rc;
1509 }
1510
1511 return 0;
1512}
int channel_load(struct secure_channel *channel, struct secure_preshared_identity *psid)
Load a pre-shared key.
Definition channel.c:783

References tls_connection::channel, channel_load(), tls_session_id::data, DBGC, DBGC_HDA, tls_session::id, tls_session_id::len, tls_session::psid, rc, tls_connection::session, and strerror().

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

1530 {
1531
1532 /* Record in transcript digest */
1533 tlskey_digest ( &tls->key, data, len );
1534
1535 return 0;
1536}
void tlskey_digest(struct tls_key_schedule *tlskey, const void *data, size_t len)
Add handshake to running transcript digest.
Definition tlskey.c:416

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

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

◆ tls_tx_resume()

void tls_tx_resume ( struct tls_connection * tls)
static

Resume TX state machine.

Parameters
tlsTLS connection

Definition at line 1543 of file tls.c.

1543 {
1544 process_add ( &tls->tx.process );
1545}
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 1564 of file tls.c.

1564 {
1565
1566 /* Sanity check */
1567 assert ( ! tls->tx.pending );
1568 assert ( ! is_pending ( &tls->client.negotiation ) );
1569 assert ( ! is_pending ( &tls->server.negotiation ) );
1570 assert ( ! is_pending ( &tls->server.validation ) );
1571
1572 /* Reset secure channel */
1573 channel_reopen ( &tls->channel );
1574
1575 /* (Re)start negotiation */
1577 tls_tx_resume ( tls );
1578 pending_get ( &tls->client.negotiation );
1579 pending_get ( &tls->server.negotiation );
1580}
void channel_reopen(struct secure_channel *channel)
Reopen secure channel.
Definition channel.c:1269
void pending_get(struct pending_operation *pending)
Mark an operation as pending.
Definition pending.c:46
static int is_pending(struct pending_operation *pending)
Check if an operation is pending.
Definition pending.h:25
unsigned int pending
Pending transmissions.
Definition tls.h:397
@ TLS_TX_CLIENT_HELLO
Definition tls.h:189

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

Referenced by add_tls(), and tls_new_hello_request().

◆ tls_establish()

int tls_establish ( struct tls_connection * tls)
static

Establish secure channel.

Parameters
tlsTLS connection
Return values
rcReturn status code

Definition at line 1588 of file tls.c.

1588 {
1589 struct tls_session *session = tls->session;
1590 int rc;
1591
1592 /* Establish channel as trusted for server name */
1593 if ( ( rc = channel_establish ( &tls->channel, session->name,
1594 tls->server.root ) ) != 0 ) {
1595 DBGC ( tls, "TLS %p could not establish channel: %s\n",
1596 tls, strerror ( rc ) );
1597 return rc;
1598 }
1599
1600 /* Save session for future resumption, if applicable */
1601 if ( tls->new_id.len || tls->new_ticket.len )
1602 tls_save ( tls );
1603
1604 /* Move to end of session's connection list and allow other
1605 * connections to start making progress.
1606 */
1607 list_del ( &tls->list );
1608 list_add_tail ( &tls->list, &session->conn );
1609 tls_tx_resume_all ( session );
1610
1611 /* Send notification of a window change */
1613
1614 return 0;
1615}
int channel_establish(struct secure_channel *channel, const char *name, struct x509_root *root)
Establish channel as trusted for application data.
Definition channel.c:986
#define list_add_tail(new, head)
Add a new entry to the tail of a list.
Definition list.h:94
static int tls_save(struct tls_connection *tls)
Save session for future resumption.
Definition tls.c:1461
void xfer_window_changed(struct interface *intf)
Report change of flow control window.
Definition xfer.c:147

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

Referenced by tls_new_finished(), and tls_send_finished().

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

1626 {
1627
1628 /* Send record */
1630}

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

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

1642 {
1643 struct tls_session *session = tls->session;
1644 size_t name_len = strlen ( session->name );
1645 struct {
1646 uint16_t type;
1647 uint16_t len;
1648 struct {
1649 uint16_t len;
1650 struct {
1651 uint8_t type;
1652 uint16_t len;
1653 uint8_t name[name_len];
1654 } __attribute__ (( packed )) list[1];
1655 } __attribute__ (( packed )) data;
1656 } __attribute__ (( packed )) *server_name_ext;
1657 struct {
1658 uint16_t type;
1659 uint16_t len;
1660 struct {
1661 uint8_t max;
1662 } __attribute__ (( packed )) data;
1663 } __attribute__ (( packed )) *max_fragment_length_ext;
1664 struct {
1665 uint16_t type;
1666 uint16_t len;
1667 struct {
1668 uint16_t len;
1670 } __attribute__ (( packed )) data;
1671 } __attribute__ (( packed )) *signature_algorithms_ext;
1672 struct {
1673 uint16_t type;
1674 uint16_t len;
1675 struct {
1676 uint8_t len;
1678 sizeof ( tls->verify.client ) :0 ];
1679 } __attribute__ (( packed )) data;
1680 } __attribute__ (( packed )) *renegotiation_info_ext;
1681 struct {
1682 uint16_t type;
1683 uint16_t len;
1684 struct {
1685 uint8_t data[session->ticket.len];
1686 } __attribute__ (( packed )) data;
1687 } __attribute__ (( packed )) *session_ticket_ext;
1688 struct {
1689 uint16_t type;
1690 uint16_t len;
1691 struct {
1692 uint16_t len;
1694 } __attribute__ (( packed )) data;
1695 } __attribute__ (( packed )) *named_group_ext;
1696 struct {
1697 uint16_t type;
1698 uint16_t len;
1699 } __attribute__ (( packed )) *extended_master_secret_ext;
1700 struct {
1701 typeof ( *server_name_ext ) server_name;
1702 typeof ( *max_fragment_length_ext ) max_fragment_length;
1703 typeof ( *signature_algorithms_ext ) signature_algorithms;
1704 typeof ( *renegotiation_info_ext ) renegotiation_info;
1705 typeof ( *session_ticket_ext ) session_ticket;
1706 typeof ( *extended_master_secret_ext ) extended_master_secret;
1707 typeof ( *named_group_ext )
1708 named_group[TLS_NUM_NAMED_GROUPS ? 1 : 0];
1709 } __attribute__ (( packed )) *extensions;
1710 struct {
1711 uint32_t type_length;
1713 struct tls_random random;
1714 uint8_t session_id_len;
1715 uint8_t session_id[session->id.len];
1716 uint16_t cipher_suite_len;
1717 uint16_t cipher_suites[TLS_NUM_CIPHER_SUITES];
1718 uint8_t compression_methods_len;
1719 uint8_t compression_methods[1];
1720 uint16_t extensions_len;
1721 typeof ( *extensions ) extensions;
1722 } __attribute__ (( packed )) hello;
1723 struct tls_cipher_suite *suite;
1724 struct tls_signature_hash_algorithm *sighash;
1725 struct tls_named_group *group;
1726 unsigned int i;
1727
1728 /* Construct record */
1729 memset ( &hello, 0, sizeof ( hello ) );
1730 hello.type_length = ( cpu_to_le32 ( TLS_CLIENT_HELLO ) |
1731 htonl ( sizeof ( hello ) -
1732 sizeof ( hello.type_length ) ) );
1733 hello.version = htons ( TLS_VERSION_MAX );
1734 tls_nonce ( tls, &hello.random );
1735 hello.session_id_len = session->id.len;
1736 memcpy ( hello.session_id, session->id.data,
1737 sizeof ( hello.session_id ) );
1738 hello.cipher_suite_len = htons ( sizeof ( hello.cipher_suites ) );
1739 i = 0 ; for_each_table_entry ( suite, TLS_CIPHER_SUITES )
1740 hello.cipher_suites[i++] = suite->code;
1741 hello.compression_methods_len = sizeof ( hello.compression_methods );
1742 hello.extensions_len = htons ( sizeof ( hello.extensions ) );
1743 extensions = &hello.extensions;
1744
1745 /* Construct server name extension */
1746 server_name_ext = &extensions->server_name;
1747 server_name_ext->type = htons ( TLS_SERVER_NAME );
1748 server_name_ext->len = htons ( sizeof ( server_name_ext->data ) );
1749 server_name_ext->data.len
1750 = htons ( sizeof ( server_name_ext->data.list ) );
1751 server_name_ext->data.list[0].type = TLS_SERVER_NAME_HOST_NAME;
1752 server_name_ext->data.list[0].len
1753 = htons ( sizeof ( server_name_ext->data.list[0].name ) );
1754 memcpy ( server_name_ext->data.list[0].name, session->name,
1755 sizeof ( server_name_ext->data.list[0].name ) );
1756
1757 /* Construct maximum fragment length extension */
1758 max_fragment_length_ext = &extensions->max_fragment_length;
1759 max_fragment_length_ext->type = htons ( TLS_MAX_FRAGMENT_LENGTH );
1760 max_fragment_length_ext->len
1761 = htons ( sizeof ( max_fragment_length_ext->data ) );
1762 max_fragment_length_ext->data.max = TLS_MAX_FRAGMENT_LENGTH_VALUE;
1763
1764 /* Construct supported signature algorithms extension */
1765 signature_algorithms_ext = &extensions->signature_algorithms;
1766 signature_algorithms_ext->type = htons ( TLS_SIGNATURE_ALGORITHMS );
1767 signature_algorithms_ext->len
1768 = htons ( sizeof ( signature_algorithms_ext->data ) );
1769 signature_algorithms_ext->data.len
1770 = htons ( sizeof ( signature_algorithms_ext->data.code ) );
1772 signature_algorithms_ext->data.code[i++] = sighash->code;
1773
1774 /* Construct renegotiation information extension */
1775 renegotiation_info_ext = &extensions->renegotiation_info;
1776 renegotiation_info_ext->type = htons ( TLS_RENEGOTIATION_INFO );
1777 renegotiation_info_ext->len
1778 = htons ( sizeof ( renegotiation_info_ext->data ) );
1779 renegotiation_info_ext->data.len
1780 = sizeof ( renegotiation_info_ext->data.data );
1781 memcpy ( renegotiation_info_ext->data.data, tls->verify.client,
1782 sizeof ( renegotiation_info_ext->data.data ) );
1783
1784 /* Construct session ticket extension */
1785 session_ticket_ext = &extensions->session_ticket;
1786 session_ticket_ext->type = htons ( TLS_SESSION_TICKET );
1787 session_ticket_ext->len
1788 = htons ( sizeof ( session_ticket_ext->data ) );
1789 memcpy ( session_ticket_ext->data.data, session->ticket.data,
1790 sizeof ( session_ticket_ext->data.data ) );
1791
1792 /* Construct extended master secret extension */
1793 extended_master_secret_ext = &extensions->extended_master_secret;
1794 extended_master_secret_ext->type
1796 extended_master_secret_ext->len = 0;
1797
1798 /* Construct named groups extension, if applicable */
1799 if ( sizeof ( extensions->named_group ) ) {
1800 named_group_ext = &extensions->named_group[0];
1801 named_group_ext->type = htons ( TLS_NAMED_GROUP );
1802 named_group_ext->len
1803 = htons ( sizeof ( named_group_ext->data ) );
1804 named_group_ext->data.len
1805 = htons ( sizeof ( named_group_ext->data.code ) );
1807 if ( group->code )
1808 named_group_ext->data.code[i++] = group->code;
1809 }
1811 }
1812
1813 return action ( tls, &hello, sizeof ( hello ) );
1814}
unsigned int uint32_t
Definition stdint.h:12
#define max(x, y)
Definition ath.h:41
#define TLS_VERSION_MAX
Maximum TLS version.
Definition crypto.h:17
#define htonl(value)
Definition byteswap.h:134
#define cpu_to_le32(value)
Definition byteswap.h:108
long int random(void)
Generate a pseudo-random number between 0 and 2147483647L or 2147483562?
Definition random.c:32
uint16_t hello
Hello time.
Definition stp.h:27
int secure_renegotiation
Secure renegotiation flag.
Definition tls.h:468
uint8_t client[12]
Client verification data.
Definition tls.h:176
#define TLS_NUM_CIPHER_SUITES
Number of supported cipher suites.
Definition tls.c:519
#define TLS_NUM_SIG_HASH_ALGORITHMS
Number of supported signature and hash algorithms.
Definition tls.c:750
#define TLS_NUM_NAMED_GROUPS
Number of non-anonymous TLS named groups.
Definition tls.h:293
#define TLS_EXTENDED_MASTER_SECRET
Definition tls.h:157
#define TLS_RENEGOTIATION_INFO
Definition tls.h:163
#define TLS_MAX_FRAGMENT_LENGTH_VALUE
Advertised maximum fragment length.
Definition tls.h:489
#define TLS_CLIENT_HELLO
Definition tls.h:70
#define TLS_SERVER_NAME
Definition tls.h:134
#define TLS_SERVER_NAME_HOST_NAME
Definition tls.h:135
#define TLS_MAX_FRAGMENT_LENGTH
Definition tls.h:138
#define TLS_NAMED_GROUP
Definition tls.h:145
#define TLS_SESSION_TICKET
Definition tls.h:160
#define TLS_SIGNATURE_ALGORITHMS
Definition tls.h:154

References __attribute__, assert, tls_verify_data::client, code, tls_cipher_suite::code, tls_signature_hash_algorithm::code, cpu_to_le32, data, tls_session_id::data, tls_session_ticket::data, for_each_table_entry, group, hello, htonl, htons, tls_session::id, len, tls_session_id::len, tls_session_ticket::len, tls_session::list, max, memcpy(), memset(), name, tls_session::name, random(), tls_connection::secure_renegotiation, tls_connection::session, strlen(), tls_session::ticket, 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_nonce(), 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 1822 of file tls.c.

1822 {
1823
1824 return tls_client_hello ( tls, tls_send_handshake );
1825}
static int tls_send_handshake(struct tls_connection *tls, const void *data, size_t len)
Transmit Handshake record.
Definition tls.c:1625
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:1639

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

1833 {
1834 struct {
1836 uint8_t data[0];
1837 } __attribute__ (( packed )) *certificate;
1838 struct {
1839 uint32_t type_length;
1841 typeof ( *certificate ) certificates[0];
1842 } __attribute__ (( packed )) *certificates;
1843 struct x509_link *link;
1844 struct x509_certificate *cert;
1845 struct io_buffer *iobuf;
1846 size_t len;
1847
1848 /* Sanity check */
1849 if ( ! tls->client.chain ) {
1850 DBGC ( tls, "TLS %p has no client certificate chain\n", tls );
1851 return -ENOENT_CERT;
1852 }
1853
1854 /* Calculate length of client certificates */
1855 len = 0;
1857 cert = link->cert;
1858 len += ( sizeof ( *certificate ) + cert->raw.len );
1859 DBGC ( tls, "TLS %p sending client certificate %s\n",
1860 tls, x509_name ( cert ) );
1861 }
1862
1863 /* Allocate storage for Certificate record (which may be too
1864 * large for the stack).
1865 */
1866 iobuf = tls_alloc_iob ( tls, ( sizeof ( *certificates ) + len ) );
1867 if ( ! iobuf )
1868 return -ENOMEM_CERTIFICATE;
1869
1870 /* Populate record */
1871 certificates = iob_put ( iobuf, sizeof ( *certificates ) );
1872 certificates->type_length =
1874 htonl ( sizeof ( *certificates ) + len -
1875 sizeof ( certificates->type_length ) ) );
1876 tls_set_uint24 ( &certificates->length, len );
1878 cert = link->cert;
1879 certificate = iob_put ( iobuf, sizeof ( *certificate ) );
1880 tls_set_uint24 ( &certificate->length, cert->raw.len );
1881 memcpy ( iob_put ( iobuf, cert->raw.len ), cert->raw.data,
1882 cert->raw.len );
1883 }
1884
1885 /* Transmit record */
1886 return tls_send_record ( tls, TLS_TYPE_HANDSHAKE,
1887 iob_disown ( iobuf ) );
1888}
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:226
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:125
static void tls_set_uint24(tls24_t *field24, unsigned long value)
Set 24-bit field value.
Definition tls.c:252
#define TLS_CERTIFICATE
Definition tls.h:73
const char * x509_name(struct x509_certificate *cert)
Get X.509 certificate display name.
Definition x509.c:147

References __attribute__, tls_client::chain, tls_connection::client, cpu_to_le32, asn1_cursor::data, data, DBGC, ENOENT_CERT, 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 1896 of file tls.c.

1896 {
1897 struct tls_cipherspec *cipherspec = &tls->tx.cipherspec.pending;
1898 struct tls_cipher_suite *suite = cipherspec->suite;
1899 struct exchange_algorithm *exchange = tls->exchange;
1900 struct {
1901 uint32_t type_length;
1902 uint8_t key_len[suite->exchange->len_len];
1903 uint8_t key[0];
1904 } __attribute__ (( packed )) key_xchg;
1905 struct asn1_builder builder = { NULL, 0 };
1906 size_t len;
1907 int i;
1908 int rc;
1909
1910 /* Fail if we have not selected a key exchange algorithm */
1911 if ( ! exchange ) {
1912 DBGC ( tls, "TLS %p has no key exchange algorithm\n", tls );
1914 goto err_exchange;
1915 }
1916
1917 /* Build shareable key */
1918 if ( ( rc = tls_key_build ( tls, exchange, &builder ) ) != 0 )
1919 goto err_build;
1920 len = builder.len;
1921
1922 /* Construct record header */
1923 key_xchg.type_length =
1925 htonl ( len + sizeof ( key_xchg ) -
1926 sizeof ( key_xchg.type_length ) ) );
1927 for ( i = ( sizeof ( key_xchg.key_len ) - 1 ) ; i >= 0 ; i-- ) {
1928 key_xchg.key_len[i] = ( len & 0xff );
1929 len >>= 8;
1930 }
1931 assert ( len == 0 );
1932
1933 /* Prepend record header (as raw data in ASN.1 builder) */
1934 if ( ( rc = asn1_prepend_raw ( &builder, &key_xchg,
1935 sizeof ( key_xchg ) ) ) != 0 ) {
1936 DBGC ( tls, "TLS %p could not construct Client Key "
1937 "Exchange: %s\n", tls, strerror ( rc ) );
1938 goto err_prepend;
1939 }
1940
1941 /* Transmit Client Key Exchange record */
1942 if ( ( rc = tls_send_handshake ( tls, builder.data,
1943 builder.len ) ) != 0 ) {
1944 goto err_send;
1945 }
1946
1947 /* Generate master secret */
1948 if ( ( rc = tlskey_master ( &tls->key,
1949 tls->extended_master_secret ) ) != 0 ) {
1950 DBGC ( tls, "TLS %p could not generate master secret: %s\n",
1951 tls, strerror ( rc ) );
1952 goto err_master;
1953 }
1954
1955 err_master:
1956 err_send:
1957 err_prepend:
1958 err_build:
1959 err_exchange:
1960 free ( builder.data );
1961 return rc;
1962}
union @162305117151260234136356364136041353210355154177 key
int asn1_prepend_raw(struct asn1_builder *builder, const void *data, size_t len)
Prepend raw data to ASN.1 builder.
Definition asn1.c:1069
static void(* free)(struct refcnt *refcnt))
Definition refcnt.h:55
An ASN.1 object builder.
Definition asn1.h:29
size_t len
Length of data.
Definition asn1.h:38
A key exchange algorithm.
Definition crypto.h:210
uint8_t len_len
Length of length field in Client Key Exchange record.
Definition tls.h:228
#define ENOENT_KEY_EXCHANGE
Definition tls.c:117
static int tls_key_build(struct tls_connection *tls, struct exchange_algorithm *exchange, struct asn1_builder *builder)
Build shareable key.
Definition tls.c:1182
#define TLS_CLIENT_KEY_EXCHANGE
Definition tls.h:78
int tlskey_master(struct tls_key_schedule *tlskey, int ems)
Generate master secret.
Definition tlskey.c:557

References __attribute__, asn1_prepend_raw(), assert, tls_tx::cipherspec, cpu_to_le32, asn1_builder::data, DBGC, ENOENT_KEY_EXCHANGE, tls_cipher_suite::exchange, tls_connection::exchange, tls_connection::extended_master_secret, free, htonl, key, tls_connection::key, asn1_builder::len, len, tls_key_exchange_algorithm::len_len, NULL, tls_cipherspec_pair::pending, rc, strerror(), tls_cipherspec::suite, TLS_CLIENT_KEY_EXCHANGE, tls_key_build(), tls_send_handshake(), tlskey_master(), 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 1970 of file tls.c.

1970 {
1971 struct digest_algorithm *digest = tls->key.digest;
1972 struct asn1_cursor *key = privkey_cursor ( tls->client.key );
1973 struct tls_signature_hash_algorithm *sig_hash = NULL;
1974 struct asn1_builder builder = { NULL, 0 };
1975 struct x509_certificate *cert;
1976 struct pubkey_algorithm *pubkey;
1977 size_t digestsize = digest->digestsize;
1978 uint8_t tbshash[digestsize];
1979 int rc;
1980
1981 /* Sanity checks */
1982 if ( ! tls->client.chain ) {
1983 DBGC ( tls, "TLS %p has no client certificate chain\n", tls );
1984 rc = -ENOENT_CERT;
1985 goto err_chain;
1986 }
1987 cert = x509_first ( tls->client.chain );
1988 if ( ! cert ) {
1989 DBGC ( tls, "TLS %p has no client certificate\n", tls );
1990 rc = -ENOENT_CERT;
1991 goto err_cert;
1992 }
1993 pubkey = cert->signature_algorithm->pubkey;
1994
1995 /* TLSv1.2 and later use explicit algorithm identifiers */
1996 if ( tls_version ( tls, TLS_VERSION_TLS_1_2 ) ) {
1997 sig_hash = tls_signature_hash_algorithm ( pubkey, digest );
1998 if ( ! sig_hash ) {
1999 DBGC ( tls, "TLS %p could not identify (%s,%s) "
2000 "signature and hash algorithm\n", tls,
2001 pubkey->name, digest->name );
2003 goto err_sig_hash;
2004 }
2005 }
2006
2007 /* Generate digest */
2008 if ( ( rc = tlskey_tbshash ( &tls->key, &tls_client, digest, NULL, 0,
2009 tbshash ) ) != 0 ) {
2010 DBGC ( tls, "TLS %p could not generate CertificateVerify "
2011 "digest: %s\n", tls, strerror ( rc ) );
2012 goto err_tbshash;
2013 }
2014
2015 /* Sign digest */
2016 if ( ( rc = pubkey_sign ( pubkey, key, digest, tbshash,
2017 &builder ) ) != 0 ) {
2018 DBGC ( tls, "TLS %p could not sign %s digest using %s client "
2019 "private key: %s\n", tls, digest->name, pubkey->name,
2020 strerror ( rc ) );
2021 goto err_pubkey_sign;
2022 }
2023
2024 /* Construct Certificate Verify record */
2025 {
2026 int use_sig_hash = ( ( sig_hash == NULL ) ? 0 : 1 );
2027 struct {
2028 uint32_t type_length;
2029 uint16_t sig_hash[use_sig_hash];
2030 uint16_t signature_len;
2031 } __attribute__ (( packed )) header;
2032
2033 header.type_length = ( cpu_to_le32 ( TLS_CERTIFICATE_VERIFY ) |
2034 htonl ( builder.len +
2035 sizeof ( header ) -
2036 sizeof ( header.type_length )));
2037 if ( use_sig_hash ) {
2038 memcpy ( &header.sig_hash[0], &sig_hash->code,
2039 sizeof ( header.sig_hash[0] ) );
2040 }
2041 header.signature_len = htons ( builder.len );
2042
2043 if ( ( rc = asn1_prepend_raw ( &builder, &header,
2044 sizeof ( header ) ) ) != 0 ) {
2045 DBGC ( tls, "TLS %p could not construct Certificate "
2046 "Verify: %s\n", tls, strerror ( rc ) );
2047 goto err_prepend;
2048 }
2049 }
2050
2051 /* Transmit record */
2052 if ( ( rc = tls_send_handshake ( tls, builder.data,
2053 builder.len ) ) != 0 ) {
2054 goto err_send;
2055 }
2056
2057 err_send:
2058 err_prepend:
2059 err_pubkey_sign:
2060 err_tbshash:
2061 err_sig_hash:
2062 err_cert:
2063 err_chain:
2064 zfree ( builder.data );
2065 return rc;
2066}
struct ena_llq_option header
Header locations.
Definition ena.h:5
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
uint32_t digestsize
Digest size (i.e.
Definition pccrr.h:1
static struct asn1_cursor * privkey_cursor(struct private_key *key)
Get private key ASN.1 cursor.
Definition privkey.h:53
An ASN.1 object cursor.
Definition asn1.h:21
TLS client state.
Definition tls.h:421
struct digest_algorithm * digest
Digest algorithm.
Definition tlskey.h:104
struct asn1_algorithm * signature_algorithm
Signature algorithm.
Definition x509.h:239
#define ENOTSUP_SIG_HASH
Definition tls.c:157
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:761
#define TLS_CERTIFICATE_VERIFY
Definition tls.h:77
int tlskey_tbshash(struct tls_key_schedule *tlskey, const struct tls_endpoint *end, struct digest_algorithm *digest, const void *data, size_t len, void *tbs)
Generate signable digest value.
Definition tlskey.c:744

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, digestsize, ENOENT_CERT, 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_version(), TLS_VERSION_TLS_1_2, tlskey_tbshash(), 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 2074 of file tls.c.

2074 {
2075 static const struct {
2076 uint8_t spec;
2077 } __attribute__ (( packed )) change_cipher = {
2078 .spec = TLS_CHANGE_CIPHER_SPEC,
2079 };
2080
2082 &change_cipher, sizeof ( change_cipher ) );
2083}
uint16_t spec
ENA specification version.
Definition ena.h:15
#define TLS_CHANGE_CIPHER_SPEC
Change cipher spec magic byte.
Definition tls.h:57
#define TLS_TYPE_CHANGE_CIPHER
Change cipher content type.
Definition tls.h:54

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

2091 {
2092 struct {
2093 uint32_t type_length;
2094 uint8_t verify_data[ sizeof ( tls->verify.client ) ];
2095 } __attribute__ (( packed )) finished;
2096 int rc;
2097
2098 /* Construct client verification data */
2099 if ( ( rc = tlskey_verify ( &tls->key, &tls_client,
2100 tls->verify.client,
2101 sizeof ( tls->verify.client ) ) ) != 0 ) {
2102 DBGC ( tls, "TLS %p could not generate client verification: "
2103 "%s\n", tls, strerror ( rc ) );
2104 return rc;
2105 }
2106
2107 /* Construct record */
2108 memset ( &finished, 0, sizeof ( finished ) );
2109 finished.type_length = ( cpu_to_le32 ( TLS_FINISHED ) |
2110 htonl ( sizeof ( finished ) -
2111 sizeof ( finished.type_length ) ) );
2112 memcpy ( finished.verify_data, tls->verify.client,
2113 sizeof ( finished.verify_data ) );
2114
2115 /* Transmit record */
2116 if ( ( rc = tls_send_handshake ( tls, &finished,
2117 sizeof ( finished ) ) ) != 0 )
2118 return rc;
2119
2120 /* Mark client as finished */
2121 pending_put ( &tls->client.negotiation );
2122
2123 /* If server has finished, then establish the secure channel */
2124 if ( ( ! is_pending ( &tls->server.negotiation ) ) &&
2125 ( ( rc = tls_establish ( tls ) ) != 0 ) ) {
2126 return rc;
2127 }
2128
2129 return 0;
2130}
static int tls_establish(struct tls_connection *tls)
Establish secure channel.
Definition tls.c:1588
#define TLS_FINISHED
Definition tls.h:79

References __attribute__, tls_connection::client, tls_verify_data::client, cpu_to_le32, DBGC, htonl, is_pending(), tls_connection::key, memcpy(), memset(), tls_client::negotiation, tls_server::negotiation, pending_put(), rc, tls_connection::server, strerror(), tls_establish(), TLS_FINISHED, tls_send_handshake(), tlskey_verify(), and tls_connection::verify.

Referenced by tls_tx_step().

◆ tls_new_change_cipher()

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

Receive new Change Cipher record.

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

Definition at line 2162 of file tls.c.

2163 {
2164 const struct {
2165 uint8_t spec;
2166 } __attribute__ (( packed )) *change_cipher = iobuf->data;
2167 size_t len = iob_len ( iobuf );
2168 int rc;
2169
2170 /* Sanity check */
2171 if ( ( sizeof ( *change_cipher ) != len ) ||
2172 ( change_cipher->spec != TLS_CHANGE_CIPHER_SPEC ) ) {
2173 DBGC ( tls, "TLS %p received invalid Change Cipher\n", tls );
2174 DBGC_HD ( tls, change_cipher, len );
2175 return -EINVAL_CHANGE_CIPHER;
2176 }
2177 iob_pull ( iobuf, sizeof ( *change_cipher ) );
2178
2179 /* Change receive cipher spec */
2180 if ( ( rc = tls_change_cipher ( tls, &tls->rx.cipherspec,
2181 &tls->channel.rx ) ) != 0 ) {
2182 DBGC ( tls, "TLS %p could not activate RX cipher: %s\n",
2183 tls, strerror ( rc ) );
2184 return rc;
2185 }
2186 tls->rx.seq = ~( ( uint64_t ) 0 );
2187
2188 return 0;
2189}
unsigned long long uint64_t
Definition stdint.h:13
#define DBGC_HD(...)
Definition compiler.h:532
#define iob_pull(iobuf, len)
Definition iobuf.h:167
uint64_t seq
Sequence number.
Definition tls.h:407
#define EINVAL_CHANGE_CIPHER
Definition tls.c:53
static int tls_change_cipher(struct tls_connection *tls, struct tls_cipherspec_pair *pair, struct secure_pipe *pipe)
Activate next cipher suite.
Definition tls.c:686

References __attribute__, tls_connection::channel, tls_rx::cipherspec, io_buffer::data, DBGC, DBGC_HD, EINVAL_CHANGE_CIPHER, iob_len(), iob_pull, len, rc, secure_channel::rx, 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 2198 of file tls.c.

2199 {
2200 const struct {
2201 uint8_t level;
2202 uint8_t description;
2203 char next[0];
2204 } __attribute__ (( packed )) *alert = iobuf->data;
2205 size_t len = iob_len ( iobuf );
2206
2207 /* Sanity check */
2208 if ( sizeof ( *alert ) != len ) {
2209 DBGC ( tls, "TLS %p received overlength Alert\n", tls );
2210 DBGC_HD ( tls, alert, len );
2211 return -EINVAL_ALERT;
2212 }
2213 iob_pull ( iobuf, sizeof ( *alert ) );
2214
2215 /* Handle alert */
2216 switch ( alert->level ) {
2217 case TLS_ALERT_WARNING:
2218 switch ( alert->description ) {
2220 DBGC ( tls, "TLS %p closed by notification\n", tls );
2221 tls_close ( tls, 0 );
2222 break;
2223 default:
2224 DBGC ( tls, "TLS %p received warning alert %d\n",
2225 tls, alert->description );
2226 break;
2227 }
2228 return 0;
2229 case TLS_ALERT_FATAL:
2230 DBGC ( tls, "TLS %p received fatal alert %d\n",
2231 tls, alert->description );
2232 return -EPERM_ALERT;
2233 default:
2234 DBGC ( tls, "TLS %p received unknown alert level %d"
2235 "(alert %d)\n", tls, alert->level, alert->description );
2236 return -EIO_ALERT;
2237 }
2238}
uint32_t next
Next descriptor address.
Definition dwmac.h:11
#define EINVAL_ALERT
Definition tls.c:57
#define EPERM_ALERT
Definition tls.c:169
#define EIO_ALERT
Definition tls.c:109
#define TLS_ALERT_FATAL
Definition tls.h:83

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

2250 {
2251
2252 /* Ignore if a handshake is in progress */
2253 if ( ! tls_ready ( tls ) ) {
2254 DBGC ( tls, "TLS %p ignoring Hello Request\n", tls );
2255 return 0;
2256 }
2257
2258 /* Fail unless server supports secure renegotiation */
2259 if ( ! ( tls->secure_renegotiation && tls->extended_master_secret ) ) {
2260 DBGC ( tls, "TLS %p refusing to renegotiate insecurely\n",
2261 tls );
2262 return -EPERM_RENEG_INSECURE;
2263 }
2264
2265 /* Restart negotiation */
2266 tls_restart ( tls );
2267
2268 return 0;
2269}
static int tls_ready(struct tls_connection *tls)
Determine if TLS connection is ready for application data.
Definition tls.c:264
static void tls_restart(struct tls_connection *tls)
Restart negotiation.
Definition tls.c:1564
#define EPERM_RENEG_INSECURE
Definition tls.c:177

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

2280 {
2281 struct tls_session *session = tls->session;
2282 const struct {
2284 struct tls_random random;
2285 uint8_t session_id_len;
2286 uint8_t session_id[0];
2287 } __attribute__ (( packed )) *hello_a = data;
2288 const uint8_t *session_id;
2289 const struct {
2290 uint16_t cipher_suite;
2291 uint8_t compression_method;
2292 char next[0];
2293 } __attribute__ (( packed )) *hello_b;
2294 const struct {
2295 uint16_t len;
2296 uint8_t data[0];
2297 } __attribute__ (( packed )) *exts;
2298 const struct {
2299 uint16_t type;
2300 uint16_t len;
2301 uint8_t data[0];
2302 } __attribute__ (( packed )) *ext;
2303 const struct {
2304 uint8_t len;
2305 uint8_t data[0];
2306 } __attribute__ (( packed )) *reneg = NULL;
2307 const struct {
2308 uint8_t data[0];
2309 } __attribute__ (( packed )) *ems = NULL;
2311 size_t exts_len;
2312 size_t ext_len;
2313 size_t remaining;
2314 int rc;
2315
2316 /* Parse header */
2317 if ( ( sizeof ( *hello_a ) > len ) ||
2318 ( hello_a->session_id_len > ( len - sizeof ( *hello_a ) ) ) ||
2319 ( sizeof ( *hello_b ) > ( len - sizeof ( *hello_a ) -
2320 hello_a->session_id_len ) ) ) {
2321 DBGC ( tls, "TLS %p received underlength Server Hello\n", tls );
2322 DBGC_HD ( tls, data, len );
2323 return -EINVAL_HELLO;
2324 }
2325 session_id = hello_a->session_id;
2326 hello_b = ( ( void * ) ( session_id + hello_a->session_id_len ) );
2327
2328 /* Parse extensions, if present */
2329 remaining = ( len - sizeof ( *hello_a ) - hello_a->session_id_len -
2330 sizeof ( *hello_b ) );
2331 if ( remaining ) {
2332
2333 /* Parse extensions length */
2334 exts = ( ( void * ) hello_b->next );
2335 if ( ( sizeof ( *exts ) > remaining ) ||
2336 ( ( exts_len = ntohs ( exts->len ) ) >
2337 ( remaining - sizeof ( *exts ) ) ) ) {
2338 DBGC ( tls, "TLS %p received underlength extensions\n",
2339 tls );
2340 DBGC_HD ( tls, data, len );
2341 return -EINVAL_HELLO;
2342 }
2343
2344 /* Parse extensions */
2345 for ( ext = ( ( void * ) exts->data ), remaining = exts_len ;
2346 remaining ;
2347 ext = ( ( ( void * ) ext ) + sizeof ( *ext ) + ext_len ),
2348 remaining -= ( sizeof ( *ext ) + ext_len ) ) {
2349
2350 /* Parse extension length */
2351 if ( ( sizeof ( *ext ) > remaining ) ||
2352 ( ( ext_len = ntohs ( ext->len ) ) >
2353 ( remaining - sizeof ( *ext ) ) ) ) {
2354 DBGC ( tls, "TLS %p received underlength "
2355 "extension\n", tls );
2356 DBGC_HD ( tls, data, len );
2357 return -EINVAL_HELLO;
2358 }
2359
2360 /* Record known extensions */
2361 switch ( ext->type ) {
2362 case htons ( TLS_RENEGOTIATION_INFO ) :
2363 reneg = ( ( void * ) ext->data );
2364 if ( ( sizeof ( *reneg ) > ext_len ) ||
2365 ( reneg->len >
2366 ( ext_len - sizeof ( *reneg ) ) ) ) {
2367 DBGC ( tls, "TLS %p received "
2368 "underlength renegotiation "
2369 "info\n", tls );
2370 DBGC_HD ( tls, data, len );
2371 return -EINVAL_HELLO;
2372 }
2373 break;
2375 ems = ( ( void * ) ext->data );
2376 break;
2377 }
2378 }
2379 }
2380
2381 /* Check and store protocol version */
2382 version = ntohs ( hello_a->version );
2383 if ( version < TLS_VERSION_MIN ) {
2384 DBGC ( tls, "TLS %p does not support protocol version %d.%d\n",
2385 tls, ( version >> 8 ), ( version & 0xff ) );
2386 return -ENOTSUP_VERSION;
2387 }
2388 if ( version > tls->version ) {
2389 DBGC ( tls, "TLS %p server attempted to illegally upgrade to "
2390 "protocol version %d.%d\n",
2391 tls, ( version >> 8 ), ( version & 0xff ) );
2392 return -EPROTO_VERSION;
2393 }
2394 tls->version = version;
2395 DBGC ( tls, "TLS %p using protocol version %d.%d\n",
2396 tls, ( version >> 8 ), ( version & 0xff ) );
2397
2398 /* Select cipher suite */
2399 if ( ( rc = tls_select_cipher ( tls, hello_b->cipher_suite ) ) != 0 )
2400 return rc;
2401
2402 /* Add preceding Client Hello to handshake digest
2403 *
2404 * When the Client Hello was originally sent, the digest
2405 * algorithm selected by the server's choice of cipher suite
2406 * was not yet known. This is the earliest point at which it
2407 * can be incorporated into the handshake transcript digest.
2408 */
2409 if ( ( rc = tls_client_hello ( tls, tls_add_handshake ) ) != 0 )
2410 return rc;
2411
2412 /* Handle extended master secret */
2413 tls->extended_master_secret = ( !! ems );
2414
2415 /* Check session ID */
2416 if ( hello_a->session_id_len &&
2417 ( hello_a->session_id_len == session->id.len ) &&
2418 ( memcmp ( session_id, session->id.data,
2419 session->id.len ) == 0 ) ) {
2420
2421 /* Session ID match: resume session */
2422 if ( ( rc = tls_resume ( tls ) ) != 0 )
2423 return rc;
2424
2425 } else if ( hello_a->session_id_len &&
2426 ( hello_a->session_id_len <=
2427 sizeof ( tls->new_id.data ) ) ) {
2428
2429 /* Record new session ID */
2430 tls->new_id.len = hello_a->session_id_len;
2431 memcpy ( tls->new_id.data, session_id, tls->new_id.len );
2432 DBGC ( tls, "TLS %p new session ID:\n", tls );
2433 DBGC_HDA ( tls, 0, tls->new_id.data, tls->new_id.len );
2434 }
2435
2436 /* Handle secure renegotiation */
2437 if ( tls->secure_renegotiation ) {
2438
2439 /* Secure renegotiation is expected; verify data */
2440 if ( ( reneg == NULL ) ||
2441 ( reneg->len != sizeof ( tls->verify ) ) ||
2442 ( memcmp ( reneg->data, &tls->verify,
2443 sizeof ( tls->verify ) ) != 0 ) ) {
2444 DBGC ( tls, "TLS %p server failed secure "
2445 "renegotiation\n", tls );
2446 return -EPERM_RENEG_VERIFY;
2447 }
2448
2449 } else if ( reneg != NULL ) {
2450
2451 /* Secure renegotiation is being enabled */
2452 if ( reneg->len != 0 ) {
2453 DBGC ( tls, "TLS %p server provided non-empty initial "
2454 "renegotiation\n", tls );
2455 return -EPERM_RENEG_VERIFY;
2456 }
2457 tls->secure_renegotiation = 1;
2458 }
2459
2460 return 0;
2461}
uint16_t ext
Extended status.
Definition ena.h:9
#define ENOTSUP_VERSION
Definition stp.c:46
static int tls_resume(struct tls_connection *tls)
Resume session.
Definition tls.c:1497
#define EINVAL_HELLO
Definition tls.c:61
static int tls_select_cipher(struct tls_connection *tls, unsigned int cipher_suite)
Select cipher suite.
Definition tls.c:634
#define EPROTO_VERSION
Definition tls.c:193
#define EPERM_RENEG_VERIFY
Definition tls.c:181

References __attribute__, data, tls_session_id::data, DBGC, DBGC_HD, DBGC_HDA, EINVAL_HELLO, ENOTSUP_VERSION, EPERM_RENEG_VERIFY, EPROTO_VERSION, ext, tls_connection::extended_master_secret, htons, tls_session::id, len, tls_session_id::len, memcmp(), memcpy(), tls_connection::new_id, next, ntohs, NULL, random(), rc, tls_connection::secure_renegotiation, tls_connection::session, tls_add_handshake(), tls_client_hello(), TLS_EXTENDED_MASTER_SECRET, TLS_RENEGOTIATION_INFO, tls_resume(), 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 2471 of file tls.c.

2472 {
2473 const struct {
2475 uint16_t len;
2476 uint8_t ticket[0];
2477 } __attribute__ (( packed )) *new_session_ticket = data;
2478 size_t ticket_len;
2479
2480 /* Parse header */
2481 if ( sizeof ( *new_session_ticket ) > len ) {
2482 DBGC ( tls, "TLS %p received underlength New Session Ticket\n",
2483 tls );
2484 DBGC_HD ( tls, data, len );
2485 return -EINVAL_TICKET;
2486 }
2487 ticket_len = ntohs ( new_session_ticket->len );
2488 if ( ticket_len > ( len - sizeof ( *new_session_ticket ) ) ) {
2489 DBGC ( tls, "TLS %p received overlength New Session Ticket\n",
2490 tls );
2491 DBGC_HD ( tls, data, len );
2492 return -EINVAL_TICKET;
2493 }
2494
2495 /* Free any unapplied new session ticket */
2496 zfree ( tls->new_ticket.data );
2497 tls->new_ticket.data = NULL;
2498 tls->new_ticket.len = 0;
2499
2500 /* Record ticket */
2501 tls->new_ticket.data = malloc ( ticket_len );
2502 if ( ! tls->new_ticket.data )
2503 return -ENOMEM;
2504 memcpy ( tls->new_ticket.data, new_session_ticket->ticket,
2505 ticket_len );
2506 tls->new_ticket.len = ticket_len;
2507 DBGC ( tls, "TLS %p new session ticket:\n", tls );
2508 DBGC_HDA ( tls, 0, tls->new_ticket.data, tls->new_ticket.len );
2509
2510 return 0;
2511}
void * malloc(size_t size)
Allocate memory.
Definition malloc.c:677
#define EINVAL_TICKET
Definition tls.c:101
u32 lifetime
For Lifetime-type KDEs, the lifetime in seconds.
Definition wpa.h:27

References __attribute__, data, tls_session_ticket::data, DBGC, DBGC_HD, DBGC_HDA, EINVAL_TICKET, ENOMEM, len, tls_session_ticket::len, lifetime, malloc(), memcpy(), tls_connection::new_ticket, 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 2521 of file tls.c.

2522 {
2523 struct x509_certificate *cert;
2524 size_t remaining = len;
2525 int rc;
2526
2527 /* Free any existing certificate chain */
2528 x509_chain_put ( tls->server.chain );
2529 tls->server.chain = NULL;
2530
2531 /* Create certificate chain */
2532 tls->server.chain = x509_alloc_chain();
2533 if ( ! tls->server.chain ) {
2534 rc = -ENOMEM_CHAIN;
2535 goto err_alloc_chain;
2536 }
2537
2538 /* Add certificates to chain */
2539 while ( remaining ) {
2540 const struct {
2541 tls24_t length;
2542 uint8_t data[0];
2543 } __attribute__ (( packed )) *certificate = data;
2544 size_t certificate_len;
2545 size_t record_len;
2546
2547 /* Parse header */
2548 if ( sizeof ( *certificate ) > remaining ) {
2549 DBGC ( tls, "TLS %p underlength certificate:\n", tls );
2550 DBGC_HDA ( tls, 0, data, remaining );
2552 goto err_underlength;
2553 }
2554 certificate_len = tls_uint24 ( &certificate->length );
2555 if ( certificate_len > ( remaining - sizeof ( *certificate ) )){
2556 DBGC ( tls, "TLS %p overlength certificate:\n", tls );
2557 DBGC_HDA ( tls, 0, data, remaining );
2559 goto err_overlength;
2560 }
2561 record_len = ( sizeof ( *certificate ) + certificate_len );
2562
2563 /* Add certificate to chain */
2564 if ( ( rc = x509_append_raw ( tls->server.chain,
2565 certificate->data,
2566 certificate_len ) ) != 0 ) {
2567 DBGC ( tls, "TLS %p could not append certificate: %s\n",
2568 tls, strerror ( rc ) );
2569 DBGC_HDA ( tls, 0, data, remaining );
2570 goto err_parse;
2571 }
2572 cert = x509_last ( tls->server.chain );
2573 DBGC ( tls, "TLS %p found certificate %s\n",
2574 tls, x509_name ( cert ) );
2575
2576 /* Move to next certificate in list */
2577 data += record_len;
2578 remaining -= record_len;
2579 }
2580
2581 return 0;
2582
2583 err_parse:
2584 err_overlength:
2585 err_underlength:
2586 x509_chain_put ( tls->server.chain );
2587 tls->server.chain = NULL;
2588 err_alloc_chain:
2589 return rc;
2590}
#define ENOMEM_CHAIN
Definition tls.c:129
#define EINVAL_CERTIFICATE
Definition tls.c:65
static unsigned long tls_uint24(const tls24_t *field24)
Extract 24-bit field value.
Definition tls.c:241
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_server::chain, data, DBGC, DBGC_HDA, EINVAL_CERTIFICATE, ENOMEM_CHAIN, len, length, NULL, rc, tls_connection::server, strerror(), tls_uint24(), x509_alloc_chain(), x509_append_raw(), x509_chain_put(), 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 2600 of file tls.c.

2601 {
2602 const struct {
2604 uint8_t certificates[0];
2605 } __attribute__ (( packed )) *certificate = data;
2606 size_t certificates_len;
2607 int rc;
2608
2609 /* Parse header */
2610 if ( sizeof ( *certificate ) > len ) {
2611 DBGC ( tls, "TLS %p received underlength Server Certificate\n",
2612 tls );
2613 DBGC_HD ( tls, data, len );
2614 return -EINVAL_CERTIFICATES;
2615 }
2616 certificates_len = tls_uint24 ( &certificate->length );
2617 if ( certificates_len > ( len - sizeof ( *certificate ) ) ) {
2618 DBGC ( tls, "TLS %p received overlength Server Certificate\n",
2619 tls );
2620 DBGC_HD ( tls, data, len );
2621 return -EINVAL_CERTIFICATES;
2622 }
2623
2624 /* Parse certificate chain */
2625 if ( ( rc = tls_parse_chain ( tls, certificate->certificates,
2626 certificates_len ) ) != 0 )
2627 return rc;
2628
2629 return 0;
2630}
#define EINVAL_CERTIFICATES
Definition tls.c:69
static int tls_parse_chain(struct tls_connection *tls, const void *data, size_t len)
Parse certificate chain.
Definition tls.c:2521

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

2641 {
2642 struct tls_cipherspec *cipherspec = &tls->tx.cipherspec.pending;
2643 struct tls_cipher_suite *suite = cipherspec->suite;
2644 struct tls_key_exchange_parameters params;
2645 struct tls_signature_hash_algorithm *sig_hash;
2646 struct x509_certificate *cert;
2647 struct pubkey_algorithm *pubkey;
2648 struct digest_algorithm *digest;
2649 int use_sig_hash = tls_version ( tls, TLS_VERSION_TLS_1_2 );
2650 const struct {
2651 uint16_t sig_hash[use_sig_hash];
2652 uint16_t signature_len;
2653 uint8_t signature[0];
2654 } __attribute__ (( packed )) *sig;
2655 struct asn1_cursor signature;
2656 size_t remaining;
2657 int rc;
2658
2659 /* Identify server certificate */
2660 if ( ! tls->server.chain ) {
2661 DBGC ( tls, "TLS %p has no server certificate chain\n", tls );
2662 return -ENOENT_CERT;
2663 }
2664 cert = x509_first ( tls->server.chain );
2665 if ( ! cert ) {
2666 DBGC ( tls, "TLS %p has no server certificate\n", tls );
2667 return -ENOENT_CERT;
2668 }
2669
2670 /* Parse parameters */
2671 if ( ( rc = suite->exchange->parse ( tls, data, len, &params ) ) != 0)
2672 return rc;
2673 DBGC ( tls, "TLS %p using named group %s-%s\n",
2674 tls, suite->exchange->name, params.exchange->name );
2675
2676 /* Signature follows parameters */
2677 assert ( params.len <= len );
2678 sig = ( data + params.len );
2679 remaining = ( len - params.len );
2680
2681 /* Parse signature from ServerKeyExchange */
2682 if ( ( sizeof ( *sig ) > remaining ) ||
2683 ( ntohs ( sig->signature_len ) > ( remaining -
2684 sizeof ( *sig ) ) ) ) {
2685 DBGC ( tls, "TLS %p received underlength ServerKeyExchange\n",
2686 tls );
2687 DBGC_HDA ( tls, 0, data, len );
2688 return -EINVAL_KEY_EXCHANGE;
2689 }
2690 signature.data = sig->signature;
2691 signature.len = ntohs ( sig->signature_len );
2692
2693 /* Identify signature and hash algorithm */
2694 if ( use_sig_hash ) {
2695 sig_hash = tls_find_signature_hash ( sig->sig_hash[0] );
2696 if ( ! sig_hash ) {
2697 DBGC ( tls, "TLS %p unsupported signature hash "
2698 "%#04x\n", tls, sig->sig_hash[0] );
2699 return -ENOTSUP_SIG_HASH;
2700 }
2701 pubkey = sig_hash->pubkey;
2702 digest = sig_hash->digest;
2703 DBGC ( tls, "TLS %p using signature hash %s-%s\n",
2704 tls, pubkey->name, digest->name );
2705 if ( sig_hash->algorithm !=
2706 cert->subject.public_key.algorithm ) {
2707 DBGC ( tls, "TLS %p cannot use %s public key\n", tls,
2709 return -EPERM_KEY_EXCHANGE;
2710 }
2711 } else {
2712 pubkey = cipherspec->suite->pubkey;
2713 digest = &md5_sha1_algorithm;
2714 }
2715
2716 /* Generate pre-master secret */
2717 if ( ( rc = tls_key_agree ( tls, params.exchange, params.partner,
2718 params.partner_len ) ) != 0 ) {
2719 return rc;
2720 }
2721
2722 /* Verify signature */
2723 {
2724 uint8_t tbshash[digest->digestsize];
2725
2726 /* Calculate digest */
2727 if ( ( rc = tlskey_tbshash ( &tls->key, &tls_server,
2728 digest, data, params.len,
2729 tbshash ) ) != 0 ) {
2730 DBGC ( tls, "TLS %p could not generate "
2731 "ServerKeyExchange digest: %s\n",
2732 tls, strerror ( rc ) );
2733 return rc;
2734 }
2735
2736 /* Verify signature to bind pre-master secret */
2737 if ( ( rc = channel_bind_verify ( &tls->channel, cert,
2738 pubkey, digest, tbshash,
2739 &signature ) ) != 0 ) {
2740 DBGC ( tls, "TLS %p ServerKeyExchange failed "
2741 "verification: %s\n", tls, strerror ( rc ) );
2742 DBGC_HDA ( tls, 0, data, len );
2743 return rc;
2744 }
2745 }
2746
2747 /* Record key exchange algorithm for sending ClientKeyExchange */
2748 tls->exchange = params.exchange;
2749
2750 return 0;
2751}
u8 sig
Definition CIB_PRM.h:15
u8 signature
CPU signature.
Definition CIB_PRM.h:7
int channel_bind_verify(struct secure_channel *channel, struct x509_certificate *identity, struct pubkey_algorithm *pubkey, struct digest_algorithm *digest, const void *value, const struct asn1_cursor *signature)
Bind peer identity via ephemeral public key signature verification.
Definition channel.c:611
const char * name
Name.
Definition asn1.h:431
int(* parse)(struct tls_connection *tls, const void *data, size_t len, struct tls_key_exchange_parameters *params)
Parse key exchange parameters from Server Key Exchange record.
Definition tls.h:224
TLS key exchange parameters.
Definition tls.h:198
struct asn1_algorithm * algorithm
Required certificate OID-identified algorithm.
Definition tls.h:329
#define EPERM_KEY_EXCHANGE
Definition tls.c:185
static int tls_key_agree(struct tls_connection *tls, struct exchange_algorithm *exchange, const void *partner, size_t len)
Agree shared secret.
Definition tls.c:1082
static struct tls_signature_hash_algorithm * tls_find_signature_hash(unsigned int code)
Find TLS signature and hash algorithm.
Definition tls.c:783

References __attribute__, tls_signature_hash_algorithm::algorithm, x509_public_key::algorithm, assert, tls_server::chain, tls_connection::channel, channel_bind_verify(), tls_tx::cipherspec, data, DBGC, DBGC_HDA, tls_signature_hash_algorithm::digest, digest_algorithm::digestsize, EINVAL_KEY_EXCHANGE, ENOENT_CERT, ENOTSUP_SIG_HASH, EPERM_KEY_EXCHANGE, tls_cipher_suite::exchange, tls_connection::exchange, tls_key_exchange_parameters::exchange, tls_connection::key, len, tls_key_exchange_parameters::len, md5_sha1_algorithm, asn1_algorithm::name, digest_algorithm::name, exchange_algorithm::name, pubkey_algorithm::name, tls_key_exchange_algorithm::name, ntohs, tls_key_exchange_algorithm::parse, tls_key_exchange_parameters::partner, tls_key_exchange_parameters::partner_len, tls_cipherspec_pair::pending, tls_cipher_suite::pubkey, tls_signature_hash_algorithm::pubkey, x509_subject::public_key, rc, tls_connection::server, sig, signature, strerror(), x509_certificate::subject, tls_cipherspec::suite, tls_find_signature_hash(), tls_key_agree(), tls_version(), TLS_VERSION_TLS_1_2, tlskey_tbshash(), tls_connection::tx, and x509_first().

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

2763 {
2764 struct x509_certificate *cert;
2765 int rc;
2766
2767 /* We can only send a single certificate, so there is no point
2768 * in parsing the Certificate Request.
2769 */
2770
2771 /* Free any existing client certificate chain */
2772 x509_chain_put ( tls->client.chain );
2773 tls->client.chain = NULL;
2774
2775 /* Create client certificate chain */
2776 tls->client.chain = x509_alloc_chain();
2777 if ( ! tls->client.chain ) {
2778 rc = -ENOMEM;
2779 goto err_alloc;
2780 }
2781
2782 /* Determine client certificate to be sent, if any */
2783 cert = x509_find_key ( NULL, tls->client.key );
2784 if ( cert ) {
2785 DBGC ( tls, "TLS %p selected client certificate %s\n",
2786 tls, x509_name ( cert ) );
2787
2788 /* Append client certificate to chain */
2789 if ( ( rc = x509_append ( tls->client.chain, cert ) ) != 0 )
2790 goto err_append;
2791
2792 /* Append any relevant issuer certificates */
2793 if ( ( rc = x509_auto_append ( tls->client.chain,
2794 &certstore ) ) != 0 )
2795 goto err_auto_append;
2796 } else {
2797
2798 /* Send an empty certificate chain */
2799 DBGC ( tls, "TLS %p could not find certificate corresponding "
2800 "to private key\n", tls );
2801 }
2802
2803 return 0;
2804
2805 err_auto_append:
2806 err_append:
2807 x509_chain_put ( tls->client.chain );
2808 tls->client.chain = NULL;
2809 err_alloc:
2810 return rc;
2811}
struct x509_chain certstore
Certificate store.
Definition certstore.c:90
int x509_auto_append(struct x509_chain *chain, struct x509_chain *store)
Append X.509 certificates to X.509 certificate chain.
Definition x509.c:1888
struct x509_certificate * x509_find_key(struct x509_chain *store, struct private_key *key)
Identify X.509 certificate by corresponding public key.
Definition x509.c:1855
int x509_append(struct x509_chain *chain, struct x509_certificate *cert)
Append X.509 certificate to X.509 certificate chain.
Definition x509.c:1638

References __unused, certstore, tls_client::chain, tls_connection::client, 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 2821 of file tls.c.

2822 {
2823 const struct {
2824 char next[0];
2825 } __attribute__ (( packed )) *hello_done = data;
2826 int rc;
2827
2828 /* Sanity checks */
2829 if ( sizeof ( *hello_done ) != len ) {
2830 DBGC ( tls, "TLS %p received overlength Server Hello Done\n",
2831 tls );
2832 DBGC_HD ( tls, data, len );
2833 return -EINVAL_HELLO_DONE;
2834 }
2835 if ( is_pending ( &tls->server.validation ) ) {
2836 DBGC ( tls, "TLS %p received duplicate Server Hello Done\n",
2837 tls );
2838 return -EINVAL_HELLO_DONE;
2839 }
2840
2841 /* Begin certificate validation */
2842 if ( ( rc = create_validator ( &tls->server.validator,
2843 tls->server.chain,
2844 tls->server.root ) ) != 0 ) {
2845 DBGC ( tls, "TLS %p could not start certificate validation: "
2846 "%s\n", tls, strerror ( rc ) );
2847 return rc;
2848 }
2849 pending_get ( &tls->server.validation );
2850
2851 return 0;
2852}
#define EINVAL_HELLO_DONE
Definition tls.c:73
int create_validator(struct interface *job, struct x509_chain *chain, struct x509_root *root)
Instantiate a certificate validator.
Definition validator.c:795

References __attribute__, tls_server::chain, create_validator(), data, DBGC, DBGC_HD, EINVAL_HELLO_DONE, is_pending(), 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 2862 of file tls.c.

2863 {
2864 int rc;
2865
2866 /* Confirm peer identity */
2867 if ( ( rc = channel_confirm ( &tls->channel, data, len ) ) != 0 ) {
2868 DBGC ( tls, "TLS %p could not confirm peer identity: %s\n",
2869 tls, strerror ( rc ) );
2870 return rc;
2871 }
2872
2873 /* Mark server as finished */
2874 pending_put ( &tls->server.negotiation );
2875
2876 /* If client has finished, then establish the secure channel */
2877 if ( ( ! is_pending ( &tls->client.negotiation ) ) &&
2878 ( ( rc = tls_establish ( tls ) ) != 0 ) ) {
2879 return rc;
2880 }
2881
2882 /* If we are resuming a session (i.e. if the server Finished
2883 * arrives before the client Finished is sent), then schedule
2884 * transmission of Change Cipher and Finished.
2885 */
2886 if ( is_pending ( &tls->client.negotiation ) ) {
2888 tls_tx_resume ( tls );
2889 }
2890
2891 return 0;
2892}
int channel_confirm(struct secure_channel *channel, const void *auth, size_t len)
Confirm peer identity.
Definition channel.c:896
@ TLS_TX_FINISHED
Definition tls.h:194
@ TLS_TX_CHANGE_CIPHER
Definition tls.h:193

References tls_connection::channel, channel_confirm(), tls_connection::client, data, DBGC, is_pending(), len, tls_client::negotiation, tls_server::negotiation, tls_tx::pending, pending_put(), rc, tls_connection::server, strerror(), tls_establish(), TLS_TX_CHANGE_CIPHER, TLS_TX_FINISHED, tls_tx_resume(), and tls_connection::tx.

Referenced by tls_new_handshake().

◆ tls_new_handshake()

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

Receive new Handshake record.

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

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

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

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

Definition at line 2922 of file tls.c.

2923 {
2924 size_t remaining;
2925 int rc;
2926
2927 while ( ( remaining = iob_len ( iobuf ) ) ) {
2928 const struct {
2929 uint8_t type;
2931 uint8_t payload[0];
2932 } __attribute__ (( packed )) *handshake = iobuf->data;
2933 const void *payload;
2934 size_t payload_len;
2935 size_t record_len;
2936
2937 /* Parse header */
2938 if ( sizeof ( *handshake ) > remaining ) {
2939 /* Leave remaining fragment unconsumed */
2940 break;
2941 }
2942 payload_len = tls_uint24 ( &handshake->length );
2943 if ( payload_len > ( remaining - sizeof ( *handshake ) ) ) {
2944 /* Leave remaining fragment unconsumed */
2945 break;
2946 }
2947 payload = &handshake->payload;
2948 record_len = ( sizeof ( *handshake ) + payload_len );
2949
2950 /* Handle payload */
2951 switch ( handshake->type ) {
2952 case TLS_HELLO_REQUEST:
2953 rc = tls_new_hello_request ( tls, payload,
2954 payload_len );
2955 break;
2956 case TLS_SERVER_HELLO:
2957 rc = tls_new_server_hello ( tls, payload, payload_len );
2958 break;
2960 rc = tls_new_session_ticket ( tls, payload,
2961 payload_len );
2962 break;
2963 case TLS_CERTIFICATE:
2964 rc = tls_new_certificate ( tls, payload, payload_len );
2965 break;
2967 rc = tls_new_server_key_exchange ( tls, payload,
2968 payload_len );
2969 break;
2971 rc = tls_new_certificate_request ( tls, payload,
2972 payload_len );
2973 break;
2975 rc = tls_new_server_hello_done ( tls, payload,
2976 payload_len );
2977 break;
2978 case TLS_FINISHED:
2979 rc = tls_new_finished ( tls, payload, payload_len );
2980 break;
2981 default:
2982 DBGC ( tls, "TLS %p ignoring handshake type %d\n",
2983 tls, handshake->type );
2984 rc = 0;
2985 break;
2986 }
2987
2988 /* Add to handshake digest (except for Hello Requests,
2989 * which are explicitly excluded).
2990 */
2991 if ( handshake->type != TLS_HELLO_REQUEST )
2992 tls_add_handshake ( tls, handshake, record_len );
2993
2994 /* Abort on failure */
2995 if ( rc != 0 )
2996 return rc;
2997
2998 /* Move to next handshake record */
2999 iob_pull ( iobuf, record_len );
3000 }
3001
3002 return 0;
3003}
static int tls_new_finished(struct tls_connection *tls, const void *data, size_t len)
Receive new Finished handshake record.
Definition tls.c:2862
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:2279
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:2761
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:2471
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:2248
static int tls_new_certificate(struct tls_connection *tls, const void *data, size_t len)
Receive new Certificate handshake record.
Definition tls.c:2600
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:2821
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:2640
#define TLS_SERVER_HELLO
Definition tls.h:71
#define TLS_SERVER_KEY_EXCHANGE
Definition tls.h:74
#define TLS_NEW_SESSION_TICKET
Definition tls.h:72
#define TLS_HELLO_REQUEST
Definition tls.h:69
#define TLS_CERTIFICATE_REQUEST
Definition tls.h:75
#define TLS_SERVER_HELLO_DONE
Definition tls.h:76

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

3013 {
3014
3015 /* RFC4346 says that we should just ignore unknown record types */
3016 iob_pull ( iobuf, iob_len ( iobuf ) );
3017 return 0;
3018}

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

3028 {
3029 struct io_buffer *iobuf;
3030 int rc;
3031
3032 /* Fail unless we are ready to receive data */
3033 if ( ! tls_ready ( tls ) )
3034 return -ENOTCONN;
3035
3036 /* Deliver each I/O buffer in turn */
3037 while ( ( iobuf = list_first_entry ( rx_data, struct io_buffer,
3038 list ) ) ) {
3039 list_del ( &iobuf->list );
3040 if ( ( rc = xfer_deliver_iob ( &tls->plainstream,
3041 iobuf ) ) != 0 ) {
3042 DBGC ( tls, "TLS %p could not deliver data: "
3043 "%s\n", tls, strerror ( rc ) );
3044 return rc;
3045 }
3046 }
3047
3048 return 0;
3049}
#define ENOTCONN
The socket is not connected.
Definition errno.h:613
#define list_first_entry(list, type, member)
Get the container of the first entry in a list.
Definition list.h:334

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

Referenced by tls_new_record().

◆ tls_new_record()

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

Receive new record.

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

Definition at line 3059 of file tls.c.

3060 {
3061 int ( * handler ) ( struct tls_connection *tls,
3062 struct io_buffer *iobuf );
3063 struct io_buffer *tmp = NULL;
3064 struct io_buffer **iobuf;
3065 int rc;
3066
3067 /* Deliver data records as-is to the plainstream interface */
3068 if ( type == TLS_TYPE_DATA )
3069 return tls_new_data ( tls, rx_data );
3070
3071 /* Determine handler and fragment buffer */
3072 iobuf = &tmp;
3073 switch ( type ) {
3075 handler = tls_new_change_cipher;
3076 break;
3077 case TLS_TYPE_ALERT:
3078 handler = tls_new_alert;
3079 break;
3080 case TLS_TYPE_HANDSHAKE:
3081 handler = tls_new_handshake;
3082 iobuf = &tls->rx.handshake;
3083 break;
3084 default:
3085 DBGC ( tls, "TLS %p unknown record type %d\n", tls, type );
3086 handler = tls_new_unknown;
3087 break;
3088 }
3089
3090 /* Merge into a single I/O buffer */
3091 if ( *iobuf )
3092 list_add ( &(*iobuf)->list, rx_data );
3093 *iobuf = iob_concatenate ( rx_data );
3094 if ( ! *iobuf ) {
3095 DBGC ( tls, "TLS %p could not concatenate non-data record "
3096 "type %d\n", tls, type );
3098 goto err_concatenate;
3099 }
3100
3101 /* Handle record */
3102 if ( ( rc = handler ( tls, *iobuf ) ) != 0 )
3103 goto err_handle;
3104
3105 /* Discard I/O buffer if empty */
3106 if ( ! iob_len ( *iobuf ) ) {
3107 free_iob ( *iobuf );
3108 *iobuf = NULL;
3109 }
3110
3111 /* Sanity check */
3112 assert ( tmp == NULL );
3113
3114 return 0;
3115
3116 err_handle:
3117 free_iob ( *iobuf );
3118 *iobuf = NULL;
3119 err_concatenate:
3120 return rc;
3121}
struct io_buffer * iob_concatenate(struct list_head *list)
Concatenate I/O buffers into a single buffer.
Definition iobuf.c:250
static int tls_new_change_cipher(struct tls_connection *tls, struct io_buffer *iobuf)
Receive new Change Cipher record.
Definition tls.c:2162
#define ENOMEM_RX_CONCAT
Definition tls.c:145
static int tls_new_unknown(struct tls_connection *tls __unused, struct io_buffer *iobuf)
Receive new unknown record.
Definition tls.c:3012
static int tls_new_data(struct tls_connection *tls, struct list_head *rx_data)
Receive new data record.
Definition tls.c:3027
static int tls_new_handshake(struct tls_connection *tls, struct io_buffer *iobuf)
Receive new Handshake record.
Definition tls.c:2922
static int tls_new_alert(struct tls_connection *tls, struct io_buffer *iobuf)
Receive new Alert record.
Definition tls.c:2198
#define TLS_TYPE_DATA
Application data content type.
Definition tls.h:66

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

3138 {
3139 struct tls_cipher_suite *suite = cipherspec->suite;
3140 struct digest_algorithm *digest = suite->digest;
3141
3142 hmac_init ( digest, ctx, cipherspec->mac_secret, suite->mac_len );
3143 hmac_update ( digest, ctx, authhdr, sizeof ( *authhdr ) );
3144}
struct golan_eq_context ctx
Definition CIB_PRM.h:0
void hmac_init(struct digest_algorithm *digest, void *ctx, const void *secret, size_t len)
Initialise HMAC.
Definition hmac.c:106
static void hmac_update(struct digest_algorithm *digest, void *ctx, const void *data, size_t len)
Update HMAC.
Definition hmac.h:62

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

Referenced by tls_hmac(), and tls_hmac_list().

◆ tls_hmac_update()

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

Update HMAC.

Parameters
cipherspecCipher specification
ctxContext
dataData
lenLength of data

Definition at line 3154 of file tls.c.

3155 {
3156 struct digest_algorithm *digest = cipherspec->suite->digest;
3157
3158 hmac_update ( digest, ctx, data, len );
3159}

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

3169 {
3170 struct digest_algorithm *digest = cipherspec->suite->digest;
3171
3172 hmac_final ( digest, ctx, hmac );
3173}
void hmac_final(struct digest_algorithm *digest, void *ctx, void *hmac)
Finalise HMAC.
Definition hmac.c:124

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

Referenced by tls_hmac(), and tls_hmac_list().

◆ tls_hmac()

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

Calculate HMAC.

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

Definition at line 3184 of file tls.c.

3186 {
3187 struct digest_algorithm *digest = cipherspec->suite->digest;
3188 uint8_t ctx[ hmac_ctxsize ( digest ) ];
3189
3190 tls_hmac_init ( cipherspec, ctx, authhdr );
3191 tls_hmac_update ( cipherspec, ctx, data, len );
3192 tls_hmac_final ( cipherspec, ctx, hmac );
3193}
static size_t hmac_ctxsize(struct digest_algorithm *digest)
Calculate HMAC context size.
Definition hmac.h:48
static void tls_hmac_init(struct tls_cipherspec *cipherspec, void *ctx, struct tls_auth_header *authhdr)
Initialise HMAC.
Definition tls.c:3137
static void tls_hmac_final(struct tls_cipherspec *cipherspec, void *ctx, void *hmac)
Finalise HMAC.
Definition tls.c:3168
static void tls_hmac_update(struct tls_cipherspec *cipherspec, void *ctx, const void *data, size_t len)
Update HMAC.
Definition tls.c:3154

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

3205 {
3206 struct digest_algorithm *digest = cipherspec->suite->digest;
3207 uint8_t ctx[ hmac_ctxsize ( digest ) ];
3208 struct io_buffer *iobuf;
3209
3210 tls_hmac_init ( cipherspec, ctx, authhdr );
3211 list_for_each_entry ( iobuf, list, list ) {
3212 tls_hmac_update ( cipherspec, ctx, iobuf->data,
3213 iob_len ( iobuf ) );
3214 }
3215 tls_hmac_final ( cipherspec, ctx, hmac );
3216}

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

3225 {
3226 struct tls_cipherspec *cipherspec = &tls->tx.cipherspec.active;
3227 struct tls_cipher_suite *suite = cipherspec->suite;
3228 struct secure_pipe *pipe = &tls->channel.tx;
3229 struct cipher_algorithm *cipher = pipe->cipher;
3230 struct tls_header *tlshdr;
3231 unsigned int count;
3232 size_t each;
3233
3234 /* Calculate number of records (allowing for zero-length records) */
3235 count = ( len ? ( ( len + TLS_TX_BUFSIZE - 1 ) / TLS_TX_BUFSIZE ) : 1 );
3236
3237 /* Calculate maximum additional length per record */
3238 each = ( sizeof ( *tlshdr ) + suite->record_iv_len + suite->mac_len +
3239 ( is_block_cipher ( cipher ) ? cipher->blocksize : 0 ) +
3240 cipher->authsize );
3241
3242 /* Calculate maximum total additional length */
3243 return ( count * each );
3244}
static unsigned int count
Number of entries.
Definition dwmac.h:220

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

Referenced by tls_alloc_iob(), and tls_send_record().

◆ tls_verify_padding()

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

Verify block padding.

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

Definition at line 3458 of file tls.c.

3459 {
3460 uint8_t *padding;
3461 unsigned int pad;
3462 unsigned int i;
3463 size_t len;
3464
3465 /* Extract and verify padding */
3466 padding = ( iobuf->tail - 1 );
3467 pad = *padding;
3468 len = ( pad + 1 );
3469 if ( len > iob_len ( iobuf ) ) {
3470 DBGC ( tls, "TLS %p received underlength padding\n", tls );
3471 DBGC_HD ( tls, iobuf->data, iob_len ( iobuf ) );
3472 return -EINVAL_PADDING;
3473 }
3474 for ( i = 0 ; i < pad ; i++ ) {
3475 if ( *(--padding) != pad ) {
3476 DBGC ( tls, "TLS %p received bad padding\n", tls );
3477 DBGC_HD ( tls, iobuf->data, iob_len ( iobuf ) );
3478 return -EINVAL_PADDING;
3479 }
3480 }
3481
3482 return len;
3483}
u32 pad[9]
Padding.
Definition ar9003_mac.h:23
void * tail
End of data.
Definition iobuf.h:115
#define EINVAL_PADDING
Definition tls.c:89

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

3495 {
3496 struct tls_cipherspec *cipherspec = &tls->rx.cipherspec.active;
3497 struct tls_cipher_suite *suite = cipherspec->suite;
3498 struct digest_algorithm *digest = suite->digest;
3499 struct secure_pipe *pipe = &tls->channel.rx;
3500 struct cipher_algorithm *cipher = pipe->cipher;
3501 size_t len = ntohs ( tlshdr->length );
3502 struct {
3503 uint8_t fixed[suite->fixed_iv_len];
3504 uint8_t record[suite->record_iv_len];
3505 } __attribute__ (( packed )) iv;
3506 struct tls_auth_header authhdr;
3507 uint8_t verify_mac[digest->digestsize];
3508 uint8_t verify_auth[cipher->authsize];
3509 struct io_buffer *first;
3510 struct io_buffer *last;
3511 struct io_buffer *iobuf;
3512 void *mac;
3513 void *auth;
3514 size_t check_len;
3515 int pad_len;
3516 int rc;
3517
3518 /* Sanity check */
3519 assert ( cipher == suite->cipher );
3520
3521 /* Locate first and last data buffers */
3522 assert ( ! list_empty ( rx_data ) );
3523 first = list_first_entry ( rx_data, struct io_buffer, list );
3524 last = list_last_entry ( rx_data, struct io_buffer, list );
3525
3526 /* Extract initialisation vector */
3527 if ( iob_len ( first ) < sizeof ( iv.record ) ) {
3528 DBGC ( tls, "TLS %p received underlength IV\n", tls );
3529 DBGC_HD ( tls, first->data, iob_len ( first ) );
3530 return -EINVAL_IV;
3531 }
3532 memcpy ( iv.fixed, cipherspec->fixed_iv, sizeof ( iv.fixed ) );
3533 memcpy ( iv.record, first->data, sizeof ( iv.record ) );
3534 iob_pull ( first, sizeof ( iv.record ) );
3535 len -= sizeof ( iv.record );
3536
3537 /* Extract unencrypted authentication tag */
3538 if ( iob_len ( last ) < cipher->authsize ) {
3539 DBGC ( tls, "TLS %p received underlength authentication tag\n",
3540 tls );
3541 DBGC_HD ( tls, last->data, iob_len ( last ) );
3542 return -EINVAL_MAC;
3543 }
3544 iob_unput ( last, cipher->authsize );
3545 len -= cipher->authsize;
3546 auth = last->tail;
3547
3548 /* Construct authentication data */
3549 authhdr.seq = cpu_to_be64 ( tls->rx.seq );
3550 authhdr.header.type = tlshdr->type;
3551 authhdr.header.version = tlshdr->version;
3552 authhdr.header.length = htons ( len );
3553
3554 /* Set initialisation vector */
3555 if ( ( rc = cipher_setiv ( cipher, pipe->ctx, &iv,
3556 sizeof ( iv ) ) ) != 0 ) {
3557 DBGC ( tls, "TLS %p could not set RX IV: %s\n",
3558 tls, strerror ( rc ) );
3559 return rc;
3560 }
3561
3562 /* Process authentication data, if applicable */
3563 if ( is_auth_cipher ( cipher ) ) {
3564 cipher_decrypt ( cipher, pipe->ctx, &authhdr,
3565 NULL, sizeof ( authhdr ) );
3566 }
3567
3568 /* Decrypt the received data */
3569 check_len = 0;
3570 list_for_each_entry ( iobuf, &tls->rx.data, list ) {
3571 cipher_decrypt ( cipher, pipe->ctx,
3572 iobuf->data, iobuf->data, iob_len ( iobuf ) );
3573 check_len += iob_len ( iobuf );
3574 }
3575 assert ( check_len == len );
3576
3577 /* Strip block padding, if applicable */
3578 if ( is_block_cipher ( cipher ) ) {
3579 pad_len = tls_verify_padding ( tls, last );
3580 if ( pad_len < 0 ) {
3581 /* Assume zero padding length to avoid timing attacks */
3582 pad_len = 0;
3583 }
3584 iob_unput ( last, pad_len );
3585 len -= pad_len;
3586 }
3587
3588 /* Extract decrypted MAC */
3589 if ( iob_len ( last ) < suite->mac_len ) {
3590 DBGC ( tls, "TLS %p received underlength MAC\n", tls );
3591 DBGC_HD ( tls, last->data, iob_len ( last ) );
3592 return -EINVAL_MAC;
3593 }
3594 iob_unput ( last, suite->mac_len );
3595 len -= suite->mac_len;
3596 mac = last->tail;
3597
3598 /* Dump received data */
3599 DBGC2 ( tls, "Received plaintext data:\n" );
3600 check_len = 0;
3601 list_for_each_entry ( iobuf, rx_data, list ) {
3602 DBGC2_HD ( tls, iobuf->data, iob_len ( iobuf ) );
3603 check_len += iob_len ( iobuf );
3604 }
3605 assert ( check_len == len );
3606
3607 /* Generate MAC */
3608 authhdr.header.length = htons ( len );
3609 if ( suite->mac_len )
3610 tls_hmac_list ( cipherspec, &authhdr, rx_data, verify_mac );
3611
3612 /* Generate authentication tag */
3613 cipher_auth ( cipher, pipe->ctx, verify_auth );
3614
3615 /* Verify MAC */
3616 if ( memcmp ( mac, verify_mac, suite->mac_len ) != 0 ) {
3617 DBGC ( tls, "TLS %p failed MAC verification\n", tls );
3618 return -EINVAL_MAC;
3619 }
3620
3621 /* Verify authentication tag */
3622 if ( memcmp ( auth, verify_auth, cipher->authsize ) != 0 ) {
3623 DBGC ( tls, "TLS %p failed authentication tag verification\n",
3624 tls );
3625 return -EINVAL_MAC;
3626 }
3627
3628 /* Process plaintext record */
3629 if ( ( rc = tls_new_record ( tls, tlshdr->type, rx_data ) ) != 0 )
3630 return rc;
3631
3632 return 0;
3633}
#define DBGC2_HD(...)
Definition compiler.h:549
#define cipher_decrypt(cipher, ctx, src, dst, len)
Definition crypto.h:336
#define list_last_entry(list, type, member)
Get the container of the last entry in a list.
Definition list.h:347
uint32_t first
First block in range.
Definition pccrr.h:1
#define EINVAL_IV
Definition tls.c:85
static void tls_hmac_list(struct tls_cipherspec *cipherspec, struct tls_auth_header *authhdr, struct list_head *list, void *hmac)
Calculate HMAC over list of I/O buffers.
Definition tls.c:3203
#define EINVAL_MAC
Definition tls.c:97
static int tls_verify_padding(struct tls_connection *tls, struct io_buffer *iobuf)
Verify block padding.
Definition tls.c:3458
static int tls_new_record(struct tls_connection *tls, unsigned int type, struct list_head *rx_data)
Receive new record.
Definition tls.c:3059

References __attribute__, tls_cipherspec_pair::active, assert, cipher_algorithm::authsize, tls_connection::channel, secure_pipe::cipher, tls_cipher_suite::cipher, cipher_auth(), cipher_decrypt, cipher_setiv(), tls_rx::cipherspec, cpu_to_be64, secure_pipe::ctx, io_buffer::data, tls_rx::data, DBGC, DBGC2, DBGC2_HD, DBGC_HD, tls_cipher_suite::digest, digest_algorithm::digestsize, EINVAL_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, secure_channel::rx, 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 3648 of file tls.c.

3648 {
3649
3650 /* Block window unless we are ready to accept data */
3651 if ( ! tls_ready ( tls ) )
3652 return 0;
3653
3654 return xfer_window ( &tls->cipherstream );
3655}
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 3665 of file tls.c.

3667 {
3668 int rc;
3669
3670 /* Refuse unless we are ready to accept data */
3671 if ( ! tls_ready ( tls ) ) {
3672 rc = -ENOTCONN;
3673 goto done;
3674 }
3675
3676 /* Send data record */
3677 if ( ( rc = tls_send_record ( tls, TLS_TYPE_DATA,
3678 iob_disown ( iobuf ) ) ) != 0 )
3679 goto done;
3680
3681 done:
3682 free_iob ( iobuf );
3683 return rc;
3684}
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 3693 of file tls.c.

3694 {
3695
3696 /* Return cipherstream or validator progress as applicable */
3697 if ( is_pending ( &tls->server.validation ) ) {
3698 return job_progress ( &tls->server.validator, progress );
3699 } else {
3700 return job_progress ( &tls->cipherstream, progress );
3701 }
3702}
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 3733 of file tls.c.

3733 {
3734 struct tls_cipherspec *cipherspec = &tls->rx.cipherspec.active;
3735 struct secure_pipe *pipe = &tls->channel.rx;
3736 struct cipher_algorithm *cipher = pipe->cipher;
3737 size_t iv_len = cipherspec->suite->record_iv_len;
3738 size_t data_len = ntohs ( tls->rx.header.length );
3739 size_t remaining = data_len;
3740 size_t frag_len;
3741 size_t reserve;
3742 struct io_buffer *iobuf;
3743 struct io_buffer *tmp;
3744 int rc;
3745
3746 /* Sanity check */
3747 assert ( ( TLS_RX_BUFSIZE % cipher->alignsize ) == 0 );
3748
3749 /* Calculate alignment reservation at start of first data buffer */
3750 reserve = ( ( -iv_len ) & ( cipher->alignsize - 1 ) );
3751 remaining += reserve;
3752
3753 /* Allocate data buffers now that we know the length */
3754 assert ( list_empty ( &tls->rx.data ) );
3755 do {
3756
3757 /* Calculate fragment length. Ensure that no block is
3758 * smaller than TLS_RX_MIN_BUFSIZE (by increasing the
3759 * allocation length if necessary).
3760 */
3761 frag_len = remaining;
3762 if ( frag_len > TLS_RX_BUFSIZE )
3763 frag_len = TLS_RX_BUFSIZE;
3764 remaining -= frag_len;
3765 if ( remaining < TLS_RX_MIN_BUFSIZE ) {
3766 frag_len += remaining;
3767 remaining = 0;
3768 }
3769
3770 /* Allocate buffer */
3771 iobuf = alloc_iob_raw ( frag_len, TLS_RX_ALIGN, 0 );
3772 if ( ! iobuf ) {
3773 DBGC ( tls, "TLS %p could not allocate %zd of %zd "
3774 "bytes for receive buffer\n", tls,
3775 remaining, data_len );
3776 rc = -ENOMEM_RX_DATA;
3777 goto err;
3778 }
3779
3780 /* Ensure tailroom is exactly what we asked for. This
3781 * will result in unaligned I/O buffers when the
3782 * fragment length is unaligned, which can happen only
3783 * before we switch to using a block cipher.
3784 */
3785 iob_reserve ( iobuf, ( iob_tailroom ( iobuf ) - frag_len ) );
3786
3787 /* Ensure first buffer length will be aligned to a
3788 * multiple of the cipher alignment size after
3789 * stripping the record IV.
3790 */
3791 iob_reserve ( iobuf, reserve );
3792 reserve = 0;
3793
3794 /* Add I/O buffer to list */
3795 list_add_tail ( &iobuf->list, &tls->rx.data );
3796
3797 } while ( remaining );
3798 assert ( ! list_empty ( &tls->rx.data ) );
3799
3800 /* Move to data state */
3801 tls->rx.state = TLS_RX_DATA;
3802
3803 return 0;
3804
3805 err:
3806 list_for_each_entry_safe ( iobuf, tmp, &tls->rx.data, list ) {
3807 list_del ( &iobuf->list );
3808 free_iob ( iobuf );
3809 }
3810 return rc;
3811}
struct io_buffer * alloc_iob_raw(size_t len, size_t align, size_t offset)
Allocate I/O buffer with specified alignment and offset.
Definition iobuf.c:49
static size_t iob_tailroom(struct io_buffer *iobuf)
Calculate available space at end of an I/O buffer.
Definition iobuf.h:240
size_t alignsize
Alignment size.
Definition crypto.h:80
enum tls_rx_state state
State machine current state.
Definition tls.h:409
struct tls_header header
Current received record header.
Definition tls.h:411
#define ENOMEM_RX_DATA
Definition tls.c:141
#define TLS_RX_MIN_BUFSIZE
Minimum RX I/O buffer size.
Definition tls.h:515
#define TLS_RX_ALIGN
RX I/O buffer alignment.
Definition tls.h:518
@ TLS_RX_DATA
Definition tls.h:184
#define TLS_RX_BUFSIZE
RX I/O buffer size.
Definition tls.h:507
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_connection::channel, secure_pipe::cipher, tls_rx::cipherspec, tls_rx::data, data_len, DBGC, ENOMEM_RX_DATA, free_iob(), tls_rx::header, iob_reserve, iob_tailroom(), tls_header::length, io_buffer::list, list_add_tail, list_del, list_empty, list_for_each_entry_safe, ntohs, rc, tls_cipher_suite::record_iv_len, secure_channel::rx, tls_connection::rx, tls_rx::state, tls_cipherspec::suite, TLS_RX_ALIGN, TLS_RX_BUFSIZE, TLS_RX_DATA, TLS_RX_MIN_BUFSIZE, and tmp.

Referenced by tls_cipherstream_deliver().

◆ tls_newdata_process_data()

int tls_newdata_process_data ( struct tls_connection * tls)
static

Handle received TLS data payload.

Parameters
tlsTLS connection
Return values
rcReturned status code

Definition at line 3819 of file tls.c.

3819 {
3820 struct io_buffer *iobuf;
3821 int rc;
3822
3823 /* Move current buffer to end of list */
3824 iobuf = list_first_entry ( &tls->rx.data, struct io_buffer, list );
3825 list_del ( &iobuf->list );
3826 list_add_tail ( &iobuf->list, &tls->rx.data );
3827
3828 /* Continue receiving data if any space remains */
3829 iobuf = list_first_entry ( &tls->rx.data, struct io_buffer, list );
3830 if ( iob_tailroom ( iobuf ) )
3831 return 0;
3832
3833 /* Process record */
3834 if ( ( rc = tls_new_ciphertext ( tls, &tls->rx.header,
3835 &tls->rx.data ) ) != 0 )
3836 return rc;
3837
3838 /* Increment RX sequence number */
3839 tls->rx.seq += 1;
3840
3841 /* Return to header state */
3842 assert ( list_empty ( &tls->rx.data ) );
3843 tls->rx.state = TLS_RX_HEADER;
3844 iob_unput ( &tls->rx.iobuf, sizeof ( tls->rx.header ) );
3845
3846 return 0;
3847}
struct io_buffer iobuf
Current received record header (static I/O buffer).
Definition tls.h:413
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:3493
@ TLS_RX_HEADER
Definition tls.h:183

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

3855 {
3856
3857 /* Open window until we are ready to accept data */
3858 if ( ! tls_ready ( tls ) )
3859 return -1UL;
3860
3861 return xfer_window ( &tls->plainstream );
3862}

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

3874 {
3875 size_t frag_len;
3876 int ( * process ) ( struct tls_connection *tls );
3877 struct io_buffer *dest;
3878 int rc;
3879
3880 while ( iob_len ( iobuf ) ) {
3881
3882 /* Select buffer according to current state */
3883 switch ( tls->rx.state ) {
3884 case TLS_RX_HEADER:
3885 dest = &tls->rx.iobuf;
3887 break;
3888 case TLS_RX_DATA:
3889 dest = list_first_entry ( &tls->rx.data,
3890 struct io_buffer, list );
3891 assert ( dest != NULL );
3893 break;
3894 default:
3895 assert ( 0 );
3897 goto done;
3898 }
3899
3900 /* Copy data portion to buffer */
3901 frag_len = iob_len ( iobuf );
3902 if ( frag_len > iob_tailroom ( dest ) )
3903 frag_len = iob_tailroom ( dest );
3904 memcpy ( iob_put ( dest, frag_len ), iobuf->data, frag_len );
3905 iob_pull ( iobuf, frag_len );
3906
3907 /* Process data if buffer is now full */
3908 if ( iob_tailroom ( dest ) == 0 ) {
3909 if ( ( rc = process ( tls ) ) != 0 ) {
3910 tls_close_alert ( tls, rc );
3911 goto done;
3912 }
3913 }
3914 }
3915 rc = 0;
3916
3917 done:
3918 free_iob ( iobuf );
3919 return rc;
3920}
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:93
static int tls_newdata_process_data(struct tls_connection *tls)
Handle received TLS data payload.
Definition tls.c:3819
static int tls_newdata_process_header(struct tls_connection *tls)
Handle received TLS header.
Definition tls.c:3733
static void tls_close_alert(struct tls_connection *tls, int rc)
Send closure alert and finish with TLS connection.
Definition tls.c:414

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

3951 {
3952
3953 /* Mark validation as complete */
3954 pending_put ( &tls->server.validation );
3955
3956 /* Close validator interface */
3957 intf_restart ( &tls->server.validator, rc );
3958
3959 /* Check for validation failure */
3960 if ( rc != 0 ) {
3961 DBGC ( tls, "TLS %p certificate validation failed: %s\n",
3962 tls, strerror ( rc ) );
3963 goto err;
3964 }
3965 DBGC ( tls, "TLS %p certificate validation succeeded\n", tls );
3966
3967 /* Schedule transmission of applicable handshake messages */
3971 if ( tls->client.chain ) {
3973 if ( ! list_empty ( &tls->client.chain->links ) )
3975 }
3976 tls_tx_resume ( tls );
3977
3978 return;
3979
3980 err:
3981 tls_close_alert ( tls, rc );
3982 return;
3983}
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:191
@ TLS_TX_CERTIFICATE_VERIFY
Definition tls.h:192
@ TLS_TX_CERTIFICATE
Definition tls.h:190

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

4007 {
4008 struct tls_session *session = tls->session;
4009 struct tls_connection *conn;
4010 int rc;
4011
4012 /* Wait for cipherstream to become ready */
4013 if ( ! xfer_window ( &tls->cipherstream ) )
4014 return;
4015
4016 /* Send first pending transmission */
4017 if ( tls->tx.pending & TLS_TX_CLIENT_HELLO ) {
4018 /* Serialise server negotiations within a session, to
4019 * provide a consistent view of session IDs and
4020 * session tickets.
4021 */
4022 list_for_each_entry ( conn, &session->conn, list ) {
4023 if ( conn == tls )
4024 break;
4025 if ( is_pending ( &conn->server.negotiation ) )
4026 return;
4027 }
4028 /* Send Client Hello */
4029 if ( ( rc = tls_send_client_hello ( tls ) ) != 0 ) {
4030 DBGC ( tls, "TLS %p could not send Client Hello: %s\n",
4031 tls, strerror ( rc ) );
4032 goto err;
4033 }
4035 } else if ( tls->tx.pending & TLS_TX_CERTIFICATE ) {
4036 /* Send Certificate */
4037 if ( ( rc = tls_send_certificate ( tls ) ) != 0 ) {
4038 DBGC ( tls, "TLS %p could not send Certificate: %s\n",
4039 tls, strerror ( rc ) );
4040 goto err;
4041 }
4043 } else if ( tls->tx.pending & TLS_TX_CLIENT_KEY_EXCHANGE ) {
4044 /* Send Client Key Exchange */
4045 if ( ( rc = tls_send_client_key_exchange ( tls ) ) != 0 ) {
4046 DBGC ( tls, "TLS %p could not send Client Key "
4047 "Exchange: %s\n", tls, strerror ( rc ) );
4048 goto err;
4049 }
4051 } else if ( tls->tx.pending & TLS_TX_CERTIFICATE_VERIFY ) {
4052 /* Send Certificate Verify */
4053 if ( ( rc = tls_send_certificate_verify ( tls ) ) != 0 ) {
4054 DBGC ( tls, "TLS %p could not send Certificate "
4055 "Verify: %s\n", tls, strerror ( rc ) );
4056 goto err;
4057 }
4059 } else if ( tls->tx.pending & TLS_TX_CHANGE_CIPHER ) {
4060 /* Send Change Cipher, and then change the cipher in use */
4061 if ( ( rc = tls_send_change_cipher ( tls ) ) != 0 ) {
4062 DBGC ( tls, "TLS %p could not send Change Cipher: "
4063 "%s\n", tls, strerror ( rc ) );
4064 goto err;
4065 }
4066 if ( ( rc = tls_change_cipher ( tls, &tls->tx.cipherspec,
4067 &tls->channel.tx ) ) != 0 ) {
4068 DBGC ( tls, "TLS %p could not activate TX cipher: "
4069 "%s\n", tls, strerror ( rc ) );
4070 goto err;
4071 }
4072 tls->tx.seq = 0;
4074 } else if ( tls->tx.pending & TLS_TX_FINISHED ) {
4075 /* Send Finished */
4076 if ( ( rc = tls_send_finished ( tls ) ) != 0 ) {
4077 DBGC ( tls, "TLS %p could not send Finished: %s\n",
4078 tls, strerror ( rc ) );
4079 goto err;
4080 }
4081 tls->tx.pending &= ~TLS_TX_FINISHED;
4082 }
4083
4084 /* Reschedule process if pending transmissions remain,
4085 * otherwise send notification of a window change.
4086 */
4087 if ( tls->tx.pending ) {
4088 tls_tx_resume ( tls );
4089 } else {
4091 }
4092
4093 return;
4094
4095 err:
4096 tls_close_alert ( tls, rc );
4097}
static int tls_send_certificate(struct tls_connection *tls)
Transmit Certificate record.
Definition tls.c:1833
static int tls_send_finished(struct tls_connection *tls)
Transmit Finished record.
Definition tls.c:2091
static int tls_send_client_hello(struct tls_connection *tls)
Transmit Client Hello record.
Definition tls.c:1822
static int tls_send_client_key_exchange(struct tls_connection *tls)
Transmit Client Key Exchange record.
Definition tls.c:1896
static int tls_send_change_cipher(struct tls_connection *tls)
Transmit Change Cipher record.
Definition tls.c:2074
static int tls_send_certificate_verify(struct tls_connection *tls)
Transmit Certificate Verify record.
Definition tls.c:1970

References tls_connection::channel, tls_tx::cipherspec, tls_connection::cipherstream, tls_session::conn, DBGC, is_pending(), tls_connection::list, list_for_each_entry, tls_server::negotiation, tls_tx::pending, tls_connection::plainstream, rc, tls_tx::seq, tls_connection::server, tls_connection::session, 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(), secure_channel::tx, tls_connection::tx, xfer_window(), and xfer_window_changed().

◆ add_tls()

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

Add TLS on an interface.

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

Definition at line 4119 of file tls.c.

4120 {
4121 struct tls_connection *tls;
4122 int rc;
4123
4124 /* Allocate and initialise TLS structure */
4125 tls = malloc ( sizeof ( *tls ) );
4126 if ( ! tls ) {
4127 rc = -ENOMEM;
4128 goto err_alloc;
4129 }
4130 memset ( tls, 0, sizeof ( *tls ) );
4131 ref_init ( &tls->refcnt, free_tls );
4132 INIT_LIST_HEAD ( &tls->list );
4137 &tls->refcnt );
4138 tls->client.key = privkey_get ( key ? key : &private_key );
4140 tls->version = TLS_VERSION_MAX;
4141 tls->exchange = &exchange_null;
4143 tls_clear_digest ( tls );
4145 tls_clear_cipher ( tls, &tls->tx.cipherspec.active );
4146 tls_clear_cipher ( tls, &tls->tx.cipherspec.pending );
4148 tls_clear_cipher ( tls, &tls->rx.cipherspec.active );
4149 tls_clear_cipher ( tls, &tls->rx.cipherspec.pending );
4150 iob_populate ( &tls->rx.iobuf, &tls->rx.header, 0,
4151 sizeof ( tls->rx.header ) );
4152 INIT_LIST_HEAD ( &tls->rx.data );
4153
4154 /* Open secure channel */
4155 if ( ( rc = channel_open ( &tls->channel ) ) != 0 )
4156 goto err_channel;
4157
4158 /* Find or create session */
4159 if ( ( rc = tls_session ( tls, name ) ) != 0 )
4160 goto err_session;
4161 list_add_tail ( &tls->list, &tls->session->conn );
4162
4163 /* Start negotiation */
4164 tls_restart ( tls );
4165
4166 /* Attach to parent interface, mortalise self, and return */
4167 intf_insert ( xfer, &tls->plainstream, &tls->cipherstream );
4168 ref_put ( &tls->refcnt );
4169 return 0;
4170
4171 err_session:
4172 channel_close ( &tls->channel );
4173 err_channel:
4174 ref_put ( &tls->refcnt );
4175 err_alloc:
4176 return rc;
4177}
int channel_open(struct secure_channel *channel)
Open secure channel.
Definition channel.c:1205
static void channel_init(struct secure_channel *channel, struct secure_channel_operations *op)
Initialise secure channel.
Definition channel.h:256
struct exchange_algorithm exchange_null
void intf_insert(struct interface *intf, struct interface *upper, struct interface *lower)
Insert a filter interface.
Definition interface.c:402
static void intf_init(struct interface *intf, struct interface_descriptor *desc, struct refcnt *refcnt)
Initialise an object interface.
Definition interface.h:204
static void iob_populate(struct io_buffer *iobuf, void *data, size_t len, size_t max_len)
Create a temporary I/O buffer.
Definition iobuf.h:255
static void process_init_stopped(struct process *process, struct process_descriptor *desc, struct refcnt *refcnt)
Initialise process without adding to process list.
Definition process.h:146
struct x509_root root_certificates
Root certificates.
Definition rootcert.c:79
struct stp_switch root
Root switch.
Definition stp.h:15
A private key.
Definition privkey.h:17
struct refcnt refcnt
Reference counter.
Definition tls.h:447
static struct interface_descriptor tls_cipherstream_desc
TLS ciphertext stream interface descriptor.
Definition tls.c:3934
static struct secure_channel_operations tls_channel_ops
Secure channel operations.
Definition tls.c:1383
static struct interface_descriptor tls_validator_desc
TLS certificate validator interface descriptor.
Definition tls.c:3991
static struct interface_descriptor tls_plainstream_desc
TLS plaintext stream interface descriptor.
Definition tls.c:3716
static void free_tls(struct refcnt *refcnt)
Free TLS connection.
Definition tls.c:344
static struct process_descriptor tls_process_desc
TLS TX process descriptor.
Definition tls.c:4100

References tls_cipherspec_pair::active, tls_connection::channel, channel_close(), channel_init(), channel_open(), tls_rx::cipherspec, tls_tx::cipherspec, tls_connection::cipherstream, tls_connection::client, tls_session::conn, tls_rx::data, ENOMEM, tls_connection::exchange, exchange_null, 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_channel_ops, tls_cipherstream_desc, tls_clear_cipher(), tls_clear_digest(), tls_plainstream_desc, tls_process_desc, tls_restart(), tls_validator_desc, TLS_VERSION_MAX, tls_connection::tx, tls_server::validator, tls_connection::version, tls_cipherspec_pair::writer, and x509_root_get().

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

◆ REQUIRING_SYMBOL()

REQUIRING_SYMBOL ( add_tls )

References add_tls().

◆ REQUIRE_OBJECT()

REQUIRE_OBJECT ( config_crypto )

Variable Documentation

◆ tls_cipher_suite_null

struct tls_cipher_suite tls_cipher_suite_null
Initial value:
= {
.pubkey = &pubkey_null,
.cipher = &cipher_null,
.digest = &digest_null,
.handshake = &digest_null,
}
struct cipher_algorithm cipher_null
Definition crypto_null.c:94

Null cipher suite.

Definition at line 510 of file tls.c.

510 {
512 .pubkey = &pubkey_null,
513 .cipher = &cipher_null,
514 .digest = &digest_null,
515 .handshake = &digest_null,
516};

Referenced by tls_change_cipher(), and tls_clear_cipher().

◆ tls_null_exchange_algorithm

struct tls_key_exchange_algorithm tls_null_exchange_algorithm
Initial value:
= {
.name = "null",
.exchange = &exchange_null,
.parse = tls_parse_null,
.len_len = 0,
}
static int tls_parse_null(struct tls_connection *tls, const void *data, size_t len, struct tls_key_exchange_parameters *params __unused)
Parse key exchange parameters from unexpected Server Key Exchange record.
Definition tls.c:856

Null key exchange algorithm.

Definition at line 865 of file tls.c.

865 {
866 .name = "null",
867 .exchange = &exchange_null,
868 .parse = tls_parse_null,
869 .len_len = 0,
870};

◆ tls_pubkey_exchange_algorithm

struct tls_key_exchange_algorithm tls_pubkey_exchange_algorithm
Initial value:
= {
.name = "pubkey",
.parse = tls_parse_null,
.len_len = sizeof ( uint16_t ),
}
struct exchange_algorithm tls_classic_pre_master_algorithm
Classic pre-master secret key exchange algorithm.
Definition tlsclassic.c:101

Public key exchange algorithm.

Definition at line 873 of file tls.c.

873 {
874 .name = "pubkey",
876 .parse = tls_parse_null,
877 .len_len = sizeof ( uint16_t ),
878};

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

◆ tls_dhe_exchange_algorithm

struct tls_key_exchange_algorithm tls_dhe_exchange_algorithm
Initial value:
= {
.name = "dhe",
.exchange = &exchange_null,
.parse = tls_parse_dhe,
.len_len = sizeof ( uint16_t ),
}
static int tls_parse_dhe(struct tls_connection *tls, const void *data, size_t len, struct tls_key_exchange_parameters *params)
Parse key exchange parameters from DHE Server Key Exchange record.
Definition tls.c:889

Ephemeral Diffie-Hellman key exchange algorithm.

Definition at line 944 of file tls.c.

944 {
945 .name = "dhe",
946 .exchange = &exchange_null,
947 .parse = tls_parse_dhe,
948 .len_len = sizeof ( uint16_t ),
949};

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",
.exchange = &exchange_null,
.parse = tls_parse_ecdhe,
.len_len = sizeof ( uint8_t ),
}
static int tls_parse_ecdhe(struct tls_connection *tls, const void *data, size_t len, struct tls_key_exchange_parameters *params)
Parse key exchange parameters from ECDHE Server Key Exchange record.
Definition tls.c:960

Ephemeral Elliptic Curve Diffie-Hellman key exchange algorithm.

Definition at line 1003 of file tls.c.

1003 {
1004 .name = "ecdhe",
1005 .exchange = &exchange_null,
1006 .parse = tls_parse_ecdhe,
1007 .len_len = sizeof ( uint8_t ),
1008};

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

◆ tls_channel_ops

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

Secure channel operations.

Definition at line 1383 of file tls.c.

1383 {
1384 .reset = tls_channel_reset,
1385 .apply = tls_channel_apply,
1386 .save = tls_channel_save,
1387 .load = tls_channel_load,
1388 .verify = tls_channel_verify,
1389};

Referenced by add_tls().

◆ tls_plainstream_ops

struct interface_operation tls_plainstream_ops[]
static
Initial value:
= {
}
void intf_close(struct interface *intf, int rc)
Close an object interface.
Definition interface.c:250
#define INTF_OP(op_type, object_type, op_func)
Define an object interface operation.
Definition interface.h:33
Job progress.
Definition job.h:16
static int tls_progress(struct tls_connection *tls, struct job_progress *progress)
Report job progress.
Definition tls.c:3693
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:3665
static size_t tls_plainstream_window(struct tls_connection *tls)
Check flow control window.
Definition tls.c:3648
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 3705 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:3705

TLS plaintext stream interface descriptor.

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

TLS ciphertext stream interface operations.

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

TLS ciphertext stream interface descriptor.

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

TLS certificate validator interface operations.

Definition at line 3986 of file tls.c.

3986 {
3988};

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

TLS certificate validator interface descriptor.

Definition at line 3991 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:4007
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 4100 of file tls.c.

Referenced by add_tls().