iPXE
tls.c File Reference

Transport Layer Security Protocol. More...

#include <stdint.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>
#include <byteswap.h>
#include <ipxe/pending.h>
#include <ipxe/hmac.h>
#include <ipxe/md5.h>
#include <ipxe/sha1.h>
#include <ipxe/sha256.h>
#include <ipxe/aes.h>
#include <ipxe/rsa.h>
#include <ipxe/iobuf.h>
#include <ipxe/xfer.h>
#include <ipxe/open.h>
#include <ipxe/x509.h>
#include <ipxe/privkey.h>
#include <ipxe/certstore.h>
#include <ipxe/rootcert.h>
#include <ipxe/rbg.h>
#include <ipxe/validator.h>
#include <ipxe/job.h>
#include <ipxe/dhe.h>
#include <ipxe/ecdhe.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 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_CURVE   __einfo_error ( EINFO_ENOTSUP_CURVE )
#define EINFO_ENOTSUP_CURVE
#define EPERM_ALERT   __einfo_error ( EINFO_EPERM_ALERT )
#define EINFO_EPERM_ALERT
#define EPERM_VERIFY   __einfo_error ( EINFO_EPERM_VERIFY )
#define EINFO_EPERM_VERIFY
#define EPERM_RENEG_INSECURE   __einfo_error ( EINFO_EPERM_RENEG_INSECURE )
#define EINFO_EPERM_RENEG_INSECURE
#define EPERM_RENEG_VERIFY   __einfo_error ( EINFO_EPERM_RENEG_VERIFY )
#define EINFO_EPERM_RENEG_VERIFY
#define EPERM_KEY_EXCHANGE   __einfo_error ( EINFO_EPERM_KEY_EXCHANGE )
#define EINFO_EPERM_KEY_EXCHANGE
#define EPERM_EMS   __einfo_error ( EINFO_EPERM_EMS )
#define EINFO_EPERM_EMS
#define EPROTO_VERSION   __einfo_error ( EINFO_EPROTO_VERSION )
#define EINFO_EPROTO_VERSION
#define tls_prf_label(tls, secret, secret_len, out, out_len, label, ...)
 Generate secure pseudo-random data.
#define TLS_NUM_CIPHER_SUITES   table_num_entries ( TLS_CIPHER_SUITES )
 Number of supported cipher suites.
#define TLS_NUM_SIG_HASH_ALGORITHMS    table_num_entries ( TLS_SIG_HASH_ALGORITHMS )
 Number of supported signature and hash algorithms.
#define TLS_NUM_NAMED_CURVES   table_num_entries ( TLS_NAMED_CURVES )
 Number of supported named curves.

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_cipher (struct tls_connection *tls, struct tls_cipherspec *cipherspec)
static void tls_verify_handshake (struct tls_connection *tls, void *out)
 Calculate handshake verification hash.
static unsigned long tls_uint24 (const tls24_t *field24)
 Extract 24-bit field value.
static void tls_set_uint24 (tls24_t *field24, unsigned long value)
 Set 24-bit field value.
static int tls_ready (struct tls_connection *tls)
 Determine if TLS connection is ready for application data.
static int tls_version (struct tls_connection *tls, unsigned int version)
 Check for TLS version.
static void md5_sha1_init (void *ctx)
 Initialise MD5+SHA1 algorithm.
static void md5_sha1_update (void *ctx, const void *data, size_t len)
 Accumulate data with MD5+SHA1 algorithm.
static void md5_sha1_final (void *ctx, void *out)
 Generate MD5+SHA1 digest.
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 int tls_generate_random (struct tls_connection *tls, void *data, size_t len)
 Generate random data.
static void tls_hmac_update_va (struct digest_algorithm *digest, void *ctx, va_list args)
 Update HMAC with a list of ( data, len ) pairs.
static void tls_p_hash_va (struct tls_connection *tls, struct digest_algorithm *digest, const void *secret, size_t secret_len, void *out, size_t out_len, va_list seeds)
 Generate secure pseudo-random data using a single hash function.
static void tls_prf (struct tls_connection *tls, const void *secret, size_t secret_len, void *out, size_t out_len,...)
 Generate secure pseudo-random data.
static void tls_generate_master_secret (struct tls_connection *tls, const void *pre_master_secret, size_t pre_master_secret_len)
 Generate master secret.
static int tls_generate_keys (struct tls_connection *tls)
 Generate key material.
static void tls_clear_handshake (struct tls_connection *tls)
 Clear handshake digest algorithm.
static int tls_select_handshake (struct tls_connection *tls, struct digest_algorithm *digest)
 Select handshake digest algorithm.
static int tls_add_handshake (struct tls_connection *tls, const void *data, size_t len)
 Add handshake record to verification hash.
static struct tls_cipher_suitetls_find_cipher_suite (unsigned int cipher_suite)
 Identify cipher suite.
static void tls_clear_cipher (struct tls_connection *tls __unused, struct tls_cipherspec *cipherspec)
 Clear cipher suite.
static int tls_set_cipher (struct tls_connection *tls, struct tls_cipherspec *cipherspec, struct tls_cipher_suite *suite)
 Set cipher suite.
static int tls_select_cipher (struct tls_connection *tls, unsigned int cipher_suite)
 Select next cipher suite.
static int tls_change_cipher (struct tls_connection *tls, struct tls_cipherspec_pair *pair)
 Activate next cipher suite.
static struct tls_signature_hash_algorithm * tls_signature_hash_algorithm (struct pubkey_algorithm *pubkey, struct digest_algorithm *digest)
 Find TLS signature and hash algorithm.
static struct pubkey_algorithmtls_signature_hash_pubkey (struct tls_signature_hash_id code)
 Find TLS signature algorithm.
static struct digest_algorithmtls_signature_hash_digest (struct tls_signature_hash_id code)
 Find TLS hash algorithm.
static struct tls_named_curvetls_find_named_curve (unsigned int named_curve)
 Identify named curve.
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_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_pubkey (struct tls_connection *tls)
 Transmit Client Key Exchange record using public key exchange.
static int tls_verify_dh_params (struct tls_connection *tls, size_t param_len)
 Verify Diffie-Hellman parameter signature.
static int tls_send_client_key_exchange_dhe (struct tls_connection *tls)
 Transmit Client Key Exchange record using DHE key exchange.
static int tls_send_client_key_exchange_ecdhe (struct tls_connection *tls)
 Transmit Client Key Exchange record using ECDHE key exchange.
static int tls_send_client_key_exchange (struct tls_connection *tls)
 Transmit Client Key Exchange record.
static int tls_send_certificate_verify (struct tls_connection *tls)
 Transmit Certificate Verify record.
static int tls_send_change_cipher (struct tls_connection *tls)
 Transmit Change Cipher record.
static int tls_send_finished (struct tls_connection *tls)
 Transmit Finished record.
static int tls_new_change_cipher (struct tls_connection *tls, struct io_buffer *iobuf)
 Receive new Change Cipher record.
static int tls_new_alert (struct tls_connection *tls, struct io_buffer *iobuf)
 Receive new Alert record.
static int tls_new_hello_request (struct tls_connection *tls, const void *data __unused, size_t len __unused)
 Receive new Hello Request handshake record.
static int tls_new_server_hello (struct tls_connection *tls, const void *data, size_t len)
 Receive new Server Hello handshake record.
static int tls_new_session_ticket (struct tls_connection *tls, const void *data, size_t len)
 Receive New Session Ticket handshake record.
static int tls_parse_chain (struct tls_connection *tls, const void *data, size_t len)
 Parse certificate chain.
static int tls_new_certificate (struct tls_connection *tls, const void *data, size_t len)
 Receive new Certificate handshake record.
static int tls_new_server_key_exchange (struct tls_connection *tls, const void *data, size_t len)
 Receive new Server Key Exchange handshake record.
static int tls_new_certificate_request (struct tls_connection *tls, const void *data __unused, size_t len __unused)
 Receive new Certificate Request handshake record.
static int tls_new_server_hello_done (struct tls_connection *tls, const void *data, size_t len)
 Receive new Server Hello Done handshake record.
static int tls_new_finished (struct tls_connection *tls, const void *data, size_t len)
 Receive new Finished handshake record.
static int tls_new_handshake (struct tls_connection *tls, struct io_buffer *iobuf)
 Receive new Handshake record.
static int tls_new_unknown (struct tls_connection *tls __unused, struct io_buffer *iobuf)
 Receive new unknown record.
static int tls_new_data (struct tls_connection *tls, struct list_head *rx_data)
 Receive new data record.
static int tls_new_record (struct tls_connection *tls, unsigned int type, struct list_head *rx_data)
 Receive new record.
static void tls_hmac_init (struct tls_cipherspec *cipherspec, void *ctx, struct tls_auth_header *authhdr)
 Initialise HMAC.
static void tls_hmac_update (struct tls_cipherspec *cipherspec, void *ctx, const void *data, size_t len)
 Update HMAC.
static void tls_hmac_final (struct tls_cipherspec *cipherspec, void *ctx, void *hmac)
 Finalise HMAC.
static void tls_hmac (struct tls_cipherspec *cipherspec, struct tls_auth_header *authhdr, const void *data, size_t len, void *hmac)
 Calculate HMAC.
static void tls_hmac_list (struct tls_cipherspec *cipherspec, struct tls_auth_header *authhdr, struct list_head *list, void *hmac)
 Calculate HMAC over list of I/O buffers.
static size_t tls_iob_reserved (struct tls_connection *tls, size_t len)
 Calculate maximum additional length required for transmitted record(s)
static int tls_verify_padding (struct tls_connection *tls, struct io_buffer *iobuf)
 Verify block padding.
static int tls_new_ciphertext (struct tls_connection *tls, struct tls_header *tlshdr, struct list_head *rx_data)
 Receive new ciphertext record.
static size_t tls_plainstream_window (struct tls_connection *tls)
 Check flow control window.
static int tls_plainstream_deliver (struct tls_connection *tls, struct io_buffer *iobuf, struct xfer_metadata *meta __unused)
 Deliver datagram as raw data.
static int tls_progress (struct tls_connection *tls, struct job_progress *progress)
 Report job progress.
static int tls_newdata_process_header (struct tls_connection *tls)
 Handle received TLS header.
static int tls_newdata_process_data (struct tls_connection *tls)
 Handle received TLS data payload.
static size_t tls_cipherstream_window (struct tls_connection *tls)
 Check flow control window.
static int tls_cipherstream_deliver (struct tls_connection *tls, struct io_buffer *iobuf, struct xfer_metadata *xfer __unused)
 Receive new ciphertext.
static void tls_validator_done (struct tls_connection *tls, int rc)
 Handle certificate validation completion.
static void tls_tx_step (struct tls_connection *tls)
 TLS TX state machine.
static int tls_session (struct tls_connection *tls, const char *name)
 Find or create session for TLS connection.
int add_tls (struct interface *xfer, const char *name, struct x509_root *root, struct private_key *key)
 Add TLS on an interface.
 REQUIRING_SYMBOL (add_tls)
 REQUIRE_OBJECT (config_crypto)

Variables

static struct digest_algorithm md5_sha1_algorithm
 Hybrid MD5+SHA1 digest algorithm.
struct rsa_digestinfo_prefix rsa_md5_sha1_prefix __rsa_digestinfo_prefix
 RSA digestInfo prefix for MD5+SHA1 algorithm.
struct tls_cipher_suite tls_cipher_suite_null
 Null cipher suite.
struct tls_key_exchange_algorithm tls_pubkey_exchange_algorithm
 Public key exchange algorithm.
struct tls_key_exchange_algorithm tls_dhe_exchange_algorithm
 Ephemeral Diffie-Hellman key exchange algorithm.
struct tls_key_exchange_algorithm tls_ecdhe_exchange_algorithm
 Ephemeral Elliptic Curve Diffie-Hellman key exchange algorithm.
static struct interface_operation tls_plainstream_ops []
 TLS plaintext stream interface operations.
static struct interface_descriptor tls_plainstream_desc
 TLS plaintext stream interface descriptor.
static struct interface_operation tls_cipherstream_ops []
 TLS ciphertext stream interface operations.
static struct interface_descriptor tls_cipherstream_desc
 TLS ciphertext stream interface descriptor.
static struct interface_operation tls_validator_ops []
 TLS certificate validator interface operations.
static struct interface_descriptor tls_validator_desc
 TLS certificate validator interface descriptor.
static struct process_descriptor tls_process_desc
 TLS TX process descriptor.

Detailed Description

Transport Layer Security Protocol.

Definition in file tls.c.

Macro Definition Documentation

◆ EINVAL_CHANGE_CIPHER

#define EINVAL_CHANGE_CIPHER   __einfo_error ( EINFO_EINVAL_CHANGE_CIPHER )

Definition at line 58 of file tls.c.

Referenced by tls_new_change_cipher().

◆ EINFO_EINVAL_CHANGE_CIPHER

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

Definition at line 59 of file tls.c.

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

◆ EINVAL_ALERT

#define EINVAL_ALERT   __einfo_error ( EINFO_EINVAL_ALERT )

Definition at line 62 of file tls.c.

Referenced by tls_new_alert().

◆ EINFO_EINVAL_ALERT

#define EINFO_EINVAL_ALERT
Value:
"Invalid Alert record" )

Definition at line 63 of file tls.c.

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

◆ EINVAL_HELLO

#define EINVAL_HELLO   __einfo_error ( EINFO_EINVAL_HELLO )

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

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

◆ EINVAL_CERTIFICATE

#define EINVAL_CERTIFICATE   __einfo_error ( EINFO_EINVAL_CERTIFICATE )

Definition at line 70 of file tls.c.

Referenced by tls_parse_chain().

◆ EINFO_EINVAL_CERTIFICATE

#define EINFO_EINVAL_CERTIFICATE
Value:
"Invalid Certificate" )

Definition at line 71 of file tls.c.

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

◆ EINVAL_CERTIFICATES

#define EINVAL_CERTIFICATES   __einfo_error ( EINFO_EINVAL_CERTIFICATES )

Definition at line 74 of file tls.c.

Referenced by tls_new_certificate().

◆ EINFO_EINVAL_CERTIFICATES

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

Definition at line 75 of file tls.c.

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

◆ EINVAL_HELLO_DONE

#define EINVAL_HELLO_DONE   __einfo_error ( EINFO_EINVAL_HELLO_DONE )

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

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

◆ EINVAL_FINISHED

#define EINVAL_FINISHED   __einfo_error ( EINFO_EINVAL_FINISHED )

Definition at line 82 of file tls.c.

Referenced by tls_new_finished().

◆ EINFO_EINVAL_FINISHED

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

Definition at line 83 of file tls.c.

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

◆ EINVAL_HANDSHAKE

#define EINVAL_HANDSHAKE   __einfo_error ( EINFO_EINVAL_HANDSHAKE )

Definition at line 86 of file tls.c.

◆ EINFO_EINVAL_HANDSHAKE

#define EINFO_EINVAL_HANDSHAKE
Value:
"Invalid Handshake record" )

Definition at line 87 of file tls.c.

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

◆ EINVAL_IV

#define EINVAL_IV   __einfo_error ( EINFO_EINVAL_IV )

Definition at line 90 of file tls.c.

Referenced by tls_new_ciphertext().

◆ EINFO_EINVAL_IV

#define EINFO_EINVAL_IV
Value:
"Invalid initialisation vector" )

Definition at line 91 of file tls.c.

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

◆ EINVAL_PADDING

#define EINVAL_PADDING   __einfo_error ( EINFO_EINVAL_PADDING )

Definition at line 94 of file tls.c.

Referenced by tls_verify_padding().

◆ EINFO_EINVAL_PADDING

#define EINFO_EINVAL_PADDING
Value:
"Invalid block padding" )

Definition at line 95 of file tls.c.

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

◆ EINVAL_RX_STATE

#define EINVAL_RX_STATE   __einfo_error ( EINFO_EINVAL_RX_STATE )

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

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

◆ EINVAL_MAC

#define EINVAL_MAC   __einfo_error ( EINFO_EINVAL_MAC )

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

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

◆ EINVAL_TICKET

#define EINVAL_TICKET   __einfo_error ( EINFO_EINVAL_TICKET )

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

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

◆ EINVAL_KEY_EXCHANGE

#define EINVAL_KEY_EXCHANGE   __einfo_error ( EINFO_EINVAL_KEY_EXCHANGE )

◆ EINFO_EINVAL_KEY_EXCHANGE

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

Definition at line 111 of file tls.c.

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

◆ EIO_ALERT

#define EIO_ALERT   __einfo_error ( EINFO_EIO_ALERT )

Definition at line 114 of file tls.c.

Referenced by tls_new_alert().

◆ EINFO_EIO_ALERT

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

Definition at line 115 of file tls.c.

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

◆ ENOMEM_CONTEXT

#define ENOMEM_CONTEXT   __einfo_error ( EINFO_ENOMEM_CONTEXT )

Definition at line 118 of file tls.c.

Referenced by tls_set_cipher().

◆ EINFO_ENOMEM_CONTEXT

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

Definition at line 119 of file tls.c.

119#define EINFO_ENOMEM_CONTEXT \
120 __einfo_uniqify ( EINFO_ENOMEM, 0x01, \
121 "Not enough space for crypto context" )

◆ ENOMEM_CERTIFICATE

#define ENOMEM_CERTIFICATE   __einfo_error ( EINFO_ENOMEM_CERTIFICATE )

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

123#define EINFO_ENOMEM_CERTIFICATE \
124 __einfo_uniqify ( EINFO_ENOMEM, 0x02, \
125 "Not enough space for certificate" )

◆ ENOMEM_CHAIN

#define ENOMEM_CHAIN   __einfo_error ( EINFO_ENOMEM_CHAIN )

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

127#define EINFO_ENOMEM_CHAIN \
128 __einfo_uniqify ( EINFO_ENOMEM, 0x03, \
129 "Not enough space for certificate chain" )

◆ ENOMEM_TX_PLAINTEXT

#define ENOMEM_TX_PLAINTEXT   __einfo_error ( EINFO_ENOMEM_TX_PLAINTEXT )

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

131#define EINFO_ENOMEM_TX_PLAINTEXT \
132 __einfo_uniqify ( EINFO_ENOMEM, 0x04, \
133 "Not enough space for transmitted plaintext" )

◆ ENOMEM_TX_CIPHERTEXT

#define ENOMEM_TX_CIPHERTEXT   __einfo_error ( EINFO_ENOMEM_TX_CIPHERTEXT )

Definition at line 134 of file tls.c.

◆ EINFO_ENOMEM_TX_CIPHERTEXT

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

Definition at line 135 of file tls.c.

135#define EINFO_ENOMEM_TX_CIPHERTEXT \
136 __einfo_uniqify ( EINFO_ENOMEM, 0x05, \
137 "Not enough space for transmitted ciphertext" )

◆ ENOMEM_RX_DATA

#define ENOMEM_RX_DATA   __einfo_error ( EINFO_ENOMEM_RX_DATA )

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

139#define EINFO_ENOMEM_RX_DATA \
140 __einfo_uniqify ( EINFO_ENOMEM, 0x07, \
141 "Not enough space for received data" )

◆ ENOMEM_RX_CONCAT

#define ENOMEM_RX_CONCAT   __einfo_error ( EINFO_ENOMEM_RX_CONCAT )

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

143#define EINFO_ENOMEM_RX_CONCAT \
144 __einfo_uniqify ( EINFO_ENOMEM, 0x08, \
145 "Not enough space to concatenate received data" )

◆ ENOTSUP_CIPHER

#define ENOTSUP_CIPHER   __einfo_error ( EINFO_ENOTSUP_CIPHER )

Definition at line 146 of file tls.c.

Referenced by tls_select_cipher().

◆ EINFO_ENOTSUP_CIPHER

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

Definition at line 147 of file tls.c.

147#define EINFO_ENOTSUP_CIPHER \
148 __einfo_uniqify ( EINFO_ENOTSUP, 0x01, \
149 "Unsupported cipher" )

◆ ENOTSUP_NULL

#define ENOTSUP_NULL   __einfo_error ( EINFO_ENOTSUP_NULL )

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

151#define EINFO_ENOTSUP_NULL \
152 __einfo_uniqify ( EINFO_ENOTSUP, 0x02, \
153 "Refusing to use null cipher" )

◆ ENOTSUP_SIG_HASH

#define ENOTSUP_SIG_HASH   __einfo_error ( EINFO_ENOTSUP_SIG_HASH )

Definition at line 154 of file tls.c.

Referenced by tls_send_certificate_verify(), and tls_verify_dh_params().

◆ EINFO_ENOTSUP_SIG_HASH

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

Definition at line 155 of file tls.c.

155#define EINFO_ENOTSUP_SIG_HASH \
156 __einfo_uniqify ( EINFO_ENOTSUP, 0x03, \
157 "Unsupported signature and hash algorithm" )

◆ ENOTSUP_VERSION

#define ENOTSUP_VERSION   __einfo_error ( EINFO_ENOTSUP_VERSION )

Definition at line 158 of file tls.c.

◆ EINFO_ENOTSUP_VERSION

#define EINFO_ENOTSUP_VERSION
Value:
"Unsupported protocol version" )

Definition at line 159 of file tls.c.

159#define EINFO_ENOTSUP_VERSION \
160 __einfo_uniqify ( EINFO_ENOTSUP, 0x04, \
161 "Unsupported protocol version" )

◆ ENOTSUP_CURVE

#define ENOTSUP_CURVE   __einfo_error ( EINFO_ENOTSUP_CURVE )

Definition at line 162 of file tls.c.

Referenced by tls_send_client_key_exchange_ecdhe().

◆ EINFO_ENOTSUP_CURVE

#define EINFO_ENOTSUP_CURVE
Value:
"Unsupported elliptic curve" )

Definition at line 163 of file tls.c.

163#define EINFO_ENOTSUP_CURVE \
164 __einfo_uniqify ( EINFO_ENOTSUP, 0x05, \
165 "Unsupported elliptic curve" )

◆ EPERM_ALERT

#define EPERM_ALERT   __einfo_error ( EINFO_EPERM_ALERT )

Definition at line 166 of file tls.c.

Referenced by tls_new_alert().

◆ EINFO_EPERM_ALERT

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

Definition at line 167 of file tls.c.

167#define EINFO_EPERM_ALERT \
168 __einfo_uniqify ( EINFO_EPERM, 0x01, \
169 "Received fatal alert" )

◆ EPERM_VERIFY

#define EPERM_VERIFY   __einfo_error ( EINFO_EPERM_VERIFY )

Definition at line 170 of file tls.c.

Referenced by tls_new_finished().

◆ EINFO_EPERM_VERIFY

#define EINFO_EPERM_VERIFY
Value:
"Handshake verification failed" )

Definition at line 171 of file tls.c.

171#define EINFO_EPERM_VERIFY \
172 __einfo_uniqify ( EINFO_EPERM, 0x02, \
173 "Handshake verification failed" )

◆ EPERM_RENEG_INSECURE

#define EPERM_RENEG_INSECURE   __einfo_error ( EINFO_EPERM_RENEG_INSECURE )

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

175#define EINFO_EPERM_RENEG_INSECURE \
176 __einfo_uniqify ( EINFO_EPERM, 0x04, \
177 "Secure renegotiation not supported" )

◆ EPERM_RENEG_VERIFY

#define EPERM_RENEG_VERIFY   __einfo_error ( EINFO_EPERM_RENEG_VERIFY )

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

179#define EINFO_EPERM_RENEG_VERIFY \
180 __einfo_uniqify ( EINFO_EPERM, 0x05, \
181 "Secure renegotiation verification failed" )

◆ EPERM_KEY_EXCHANGE

#define EPERM_KEY_EXCHANGE   __einfo_error ( EINFO_EPERM_KEY_EXCHANGE )

Definition at line 182 of file tls.c.

Referenced by tls_verify_dh_params().

◆ EINFO_EPERM_KEY_EXCHANGE

#define EINFO_EPERM_KEY_EXCHANGE
Value:
"ServerKeyExchange verification failed" )

Definition at line 183 of file tls.c.

183#define EINFO_EPERM_KEY_EXCHANGE \
184 __einfo_uniqify ( EINFO_EPERM, 0x06, \
185 "ServerKeyExchange verification failed" )

◆ EPERM_EMS

#define EPERM_EMS   __einfo_error ( EINFO_EPERM_EMS )

Definition at line 186 of file tls.c.

Referenced by tls_new_server_hello().

◆ EINFO_EPERM_EMS

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

Definition at line 187 of file tls.c.

187#define EINFO_EPERM_EMS \
188 __einfo_uniqify ( EINFO_EPERM, 0x07, \
189 "Extended master secret extension mismatch" )

◆ EPROTO_VERSION

#define EPROTO_VERSION   __einfo_error ( EINFO_EPROTO_VERSION )

Definition at line 190 of file tls.c.

Referenced by tls_new_server_hello().

◆ EINFO_EPROTO_VERSION

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

Definition at line 191 of file tls.c.

191#define EINFO_EPROTO_VERSION \
192 __einfo_uniqify ( EINFO_EPROTO, 0x01, \
193 "Illegal protocol version upgrade" )

◆ tls_prf_label

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

Generate secure pseudo-random data.

Parameters
secretSecret
secret_lenLength of secret
outOutput buffer
out_lenLength of output buffer
labelString literal label
...( data, len ) pairs of seed data

Definition at line 627 of file tls.c.

627#define tls_prf_label( tls, secret, secret_len, out, out_len, label, ... ) \
628 tls_prf ( (tls), (secret), (secret_len), (out), (out_len), \
629 label, ( sizeof ( label ) - 1 ), __VA_ARGS__, NULL )

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

◆ TLS_NUM_CIPHER_SUITES

#define TLS_NUM_CIPHER_SUITES   table_num_entries ( TLS_CIPHER_SUITES )

Number of supported cipher suites.

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

1009#define TLS_NUM_SIG_HASH_ALGORITHMS \
1010 table_num_entries ( TLS_SIG_HASH_ALGORITHMS )

Referenced by tls_client_hello().

◆ TLS_NUM_NAMED_CURVES

#define TLS_NUM_NAMED_CURVES   table_num_entries ( TLS_NAMED_CURVES )

Number of supported named curves.

Definition at line 1081 of file tls.c.

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

1123 {
1124 struct tls_connection *tls;
1125
1127 tls_tx_resume ( tls );
1128}
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition list.h:432
A TLS connection.
Definition tls.h:437
struct tls_session * session
Session.
Definition tls.h:442
struct list_head list
List of connections within the same session.
Definition tls.h:444
struct list_head conn
List of connections.
Definition tls.h:369
static void tls_tx_resume(struct tls_connection *tls)
Resume TX state machine.
Definition tls.c:1114

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

Referenced by tls_close(), and tls_new_finished().

◆ tls_alloc_iob()

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

Allocate I/O buffer for transmitted record(s)

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

Definition at line 3061 of file tls.c.

3062 {
3063 struct io_buffer *iobuf;
3064 size_t reserve;
3065
3066 /* Calculate maximum additional length to reserve */
3067 reserve = tls_iob_reserved ( tls, len );
3068
3069 /* Allocate I/O buffer */
3070 iobuf = xfer_alloc_iob ( &tls->cipherstream, ( reserve + len ) );
3071 if ( ! iobuf )
3072 return NULL;
3073
3074 /* Reserve space */
3075 iob_reserve ( iobuf, reserve );
3076
3077 return iobuf;
3078}
ring len
Length.
Definition dwmac.h:226
#define iob_reserve(iobuf, len)
Definition iobuf.h:72
A persistent I/O buffer.
Definition iobuf.h:38
struct interface cipherstream
Ciphertext stream.
Definition tls.h:457
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:3034
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 2014 of file tls.c.

2015 {
2016 const struct {
2017 uint8_t level;
2018 uint8_t description;
2019 } __attribute__ (( packed )) alert = {
2020 .level = level,
2021 .description = description,
2022 };
2023
2024 /* Send record */
2025 return tls_send_plaintext ( tls, TLS_TYPE_ALERT, &alert,
2026 sizeof ( alert ) );
2027}
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:3231
#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().

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

3089 {
3090 struct tls_cipherspec *cipherspec = &tls->tx.cipherspec.active;
3091 struct tls_cipher_suite *suite = cipherspec->suite;
3092 struct cipher_algorithm *cipher = suite->cipher;
3093 struct digest_algorithm *digest = suite->digest;
3094 struct {
3095 uint8_t fixed[suite->fixed_iv_len];
3096 uint8_t rec[suite->record_iv_len];
3097 } __attribute__ (( packed )) iv;
3098 struct tls_auth_header authhdr;
3099 struct tls_header *tlshdr;
3100 uint8_t mac[digest->digestsize];
3101 const void *plaintext;
3102 const void *encrypt;
3103 void *ciphertext;
3104 size_t record_len;
3105 size_t encrypt_len;
3106 size_t pad_len;
3107 size_t len;
3108 int rc;
3109
3110 /* Record plaintext pointer and length */
3111 plaintext = iobuf->data;
3112 len = iob_len ( iobuf );
3113
3114 /* Add to handshake digest if applicable */
3115 if ( type == TLS_TYPE_HANDSHAKE )
3116 tls_add_handshake ( tls, plaintext, len );
3117
3118 /* Start constructing ciphertext at start of reserved space */
3119 iob_push ( iobuf, tls_iob_reserved ( tls, len ) );
3120 iob_unput ( iobuf, iob_len ( iobuf ) );
3121
3122 /* Construct records */
3123 do {
3124 /* Limit length of this record (may be zero) */
3125 record_len = len;
3126 if ( record_len > TLS_TX_BUFSIZE )
3127 record_len = TLS_TX_BUFSIZE;
3128
3129 /* Construct and set initialisation vector */
3130 memcpy ( iv.fixed, cipherspec->fixed_iv, sizeof ( iv.fixed ) );
3131 if ( ( rc = tls_generate_random ( tls, iv.rec,
3132 sizeof ( iv.rec ) ) ) != 0 ) {
3133 goto err_random;
3134 }
3135 cipher_setiv ( cipher, cipherspec->cipher_ctx, &iv,
3136 sizeof ( iv ) );
3137
3138 /* Construct and process authentication data */
3139 authhdr.seq = cpu_to_be64 ( tls->tx.seq );
3140 authhdr.header.type = type;
3141 authhdr.header.version = htons ( tls->version );
3142 authhdr.header.length = htons ( record_len );
3143 if ( suite->mac_len ) {
3144 tls_hmac ( cipherspec, &authhdr, plaintext, record_len,
3145 mac );
3146 }
3147 if ( is_auth_cipher ( cipher ) ) {
3148 cipher_encrypt ( cipher, cipherspec->cipher_ctx,
3149 &authhdr, NULL, sizeof ( authhdr ) );
3150 }
3151
3152 /* Calculate encryption length */
3153 encrypt_len = ( record_len + suite->mac_len );
3154 if ( is_block_cipher ( cipher ) ) {
3155 pad_len = ( ( ( cipher->blocksize - 1 ) &
3156 -( encrypt_len + 1 ) ) + 1 );
3157 } else {
3158 pad_len = 0;
3159 }
3160 encrypt_len += pad_len;
3161
3162 /* Add record header */
3163 tlshdr = iob_put ( iobuf, sizeof ( *tlshdr ) );
3164 tlshdr->type = type;
3165 tlshdr->version = htons ( tls->version );
3166 tlshdr->length = htons ( sizeof ( iv.rec ) + encrypt_len +
3167 cipher->authsize );
3168
3169 /* Add record initialisation vector, if applicable */
3170 memcpy ( iob_put ( iobuf, sizeof ( iv.rec ) ), iv.rec,
3171 sizeof ( iv.rec ) );
3172
3173 /* Copy plaintext data if necessary */
3174 ciphertext = iob_put ( iobuf, record_len );
3175 assert ( ciphertext <= plaintext );
3176 if ( encrypt_len > record_len ) {
3177 memmove ( ciphertext, plaintext, record_len );
3178 encrypt = ciphertext;
3179 } else {
3180 encrypt = plaintext;
3181 }
3182
3183 /* Add MAC, if applicable */
3184 memcpy ( iob_put ( iobuf, suite->mac_len ), mac,
3185 suite->mac_len );
3186
3187 /* Add padding, if applicable */
3188 memset ( iob_put ( iobuf, pad_len ), ( pad_len - 1 ), pad_len );
3189
3190 /* Encrypt data and append authentication tag */
3191 DBGC2 ( tls, "Sending plaintext data:\n" );
3192 DBGC2_HDA ( tls, 0, encrypt, encrypt_len );
3193 cipher_encrypt ( cipher, cipherspec->cipher_ctx, encrypt,
3194 ciphertext, encrypt_len );
3195 cipher_auth ( cipher, cipherspec->cipher_ctx,
3196 iob_put ( iobuf, cipher->authsize ) );
3197
3198 /* Move to next record */
3199 tls->tx.seq += 1;
3200 plaintext += record_len;
3201 len -= record_len;
3202
3203 } while ( len );
3204
3205 /* Send ciphertext */
3206 if ( ( rc = xfer_deliver_iob ( &tls->cipherstream,
3207 iob_disown ( iobuf ) ) ) != 0 ) {
3208 DBGC ( tls, "TLS %p could not deliver ciphertext: %s\n",
3209 tls, strerror ( rc ) );
3210 goto err_deliver;
3211 }
3212
3213 assert ( iobuf == NULL );
3214 return 0;
3215
3216 err_deliver:
3217 err_random:
3218 free_iob ( iobuf );
3219 return rc;
3220}
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
long pad_len
Definition bigint.h:31
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
struct eltorito_descriptor_fixed fixed
Fixed portion.
Definition eltorito.h:1
uint32_t type
Operating system type.
Definition ena.h:1
uint8_t mac[ETH_ALEN]
MAC address.
Definition ena.h:13
#define DBGC2(...)
Definition compiler.h:522
#define DBGC2_HDA(...)
Definition compiler.h:523
#define DBGC(...)
Definition compiler.h:505
#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:277
static void cipher_setiv(struct cipher_algorithm *cipher, void *ctx, const void *iv, size_t ivlen)
Definition crypto.h:241
static int is_auth_cipher(struct cipher_algorithm *cipher)
Definition crypto.h:282
#define cipher_encrypt(cipher, ctx, src, dst, len)
Definition crypto.h:251
static void cipher_auth(struct cipher_algorithm *cipher, void *ctx, void *auth)
Definition crypto.h:267
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void * memset(void *dest, int character, size_t len) __nonnull
void * memmove(void *dest, const void *src, size_t len) __nonnull
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition iobuf.c:153
#define iob_push(iobuf, len)
Definition iobuf.h:89
#define iob_put(iobuf, len)
Definition iobuf.h:125
#define iob_disown(iobuf)
Disown an I/O buffer.
Definition iobuf.h:217
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition iobuf.h:160
#define iob_unput(iobuf, len)
Definition iobuf.h:140
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
A cipher algorithm.
Definition crypto.h:51
size_t blocksize
Block size.
Definition crypto.h:61
size_t authsize
Authentication tag size.
Definition crypto.h:75
A message digest algorithm.
Definition crypto.h:19
size_t digestsize
Digest size.
Definition crypto.h:27
void * data
Start of data.
Definition iobuf.h:53
TLS authentication header.
Definition tls.h:158
A TLS cipher suite.
Definition tls.h:203
uint8_t fixed_iv_len
Fixed initialisation vector length.
Definition tls.h:219
struct cipher_algorithm * cipher
Bulk encryption cipher algorithm.
Definition tls.h:209
uint8_t mac_len
MAC length.
Definition tls.h:223
uint8_t record_iv_len
Record initialisation vector length.
Definition tls.h:221
struct digest_algorithm * digest
MAC digest algorithm.
Definition tls.h:211
struct tls_cipherspec active
Current cipher specification.
Definition tls.h:277
A TLS cipher specification.
Definition tls.h:261
void * fixed_iv
Fixed initialisation vector.
Definition tls.h:271
struct tls_cipher_suite * suite
Cipher suite.
Definition tls.h:263
void * cipher_ctx
Bulk encryption cipher context.
Definition tls.h:267
struct tls_tx tx
Transmit state.
Definition tls.h:475
uint16_t version
Protocol version.
Definition tls.h:460
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:377
struct tls_cipherspec_pair cipherspec
Cipher specifications.
Definition tls.h:375
static int tls_generate_random(struct tls_connection *tls, void *data, size_t len)
Generate random data.
Definition tls.c:464
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:2993
static int tls_add_handshake(struct tls_connection *tls, const void *data, size_t len)
Add handshake record to verification hash.
Definition tls.c:823
#define TLS_TX_BUFSIZE
TX maximum fragment length.
Definition tls.h:493
#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_cipher_suite::cipher, cipher_auth(), tls_cipherspec::cipher_ctx, cipher_encrypt, cipher_setiv(), tls_tx::cipherspec, tls_connection::cipherstream, cpu_to_be64, io_buffer::data, DBGC, DBGC2, DBGC2_HDA, tls_cipher_suite::digest, digest_algorithm::digestsize, fixed, tls_cipherspec::fixed_iv, tls_cipher_suite::fixed_iv_len, free_iob(), tls_auth_header::header, htons, iob_disown, iob_len(), iob_push, iob_put, iob_unput, is_auth_cipher(), is_block_cipher(), iv, len, tls_header::length, mac, tls_cipher_suite::mac_len, memcpy(), memmove(), memset(), NULL, pad_len, rc, tls_cipher_suite::record_iv_len, tls_auth_header::seq, tls_tx::seq, strerror(), tls_cipherspec::suite, tls_add_handshake(), tls_generate_random(), tls_hmac(), tls_iob_reserved(), TLS_TX_BUFSIZE, TLS_TYPE_HANDSHAKE, tls_connection::tx, tls_header::type, type, tls_connection::version, tls_header::version, and xfer_deliver_iob().

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

◆ tls_send_plaintext()

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

Send plaintext record.

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

Definition at line 3231 of file tls.c.

3232 {
3233 struct io_buffer *iobuf;
3234 int rc;
3235
3236 /* Allocate I/O buffer */
3237 iobuf = tls_alloc_iob ( tls, len );
3238 if ( ! iobuf )
3239 return -ENOMEM_TX_PLAINTEXT;
3240 memcpy ( iob_put ( iobuf, len ), data, len );
3241
3242 /* Transmit I/O buffer */
3243 if ( ( rc = tls_send_record ( tls, type, iob_disown ( iobuf ) ) ) != 0 )
3244 return rc;
3245
3246 return 0;
3247}
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:3061
static int tls_send_record(struct tls_connection *tls, unsigned int type, struct io_buffer *iobuf)
Send plaintext record(s)
Definition tls.c:3088
#define ENOMEM_TX_PLAINTEXT
Definition tls.c:130

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

Referenced by tls_send_alert(), tls_send_change_cipher(), and tls_send_handshake().

◆ tls_clear_cipher() [1/2]

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

References out.

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

◆ tls_verify_handshake()

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

Calculate handshake verification hash.

Parameters
tlsTLS connection
outOutput buffer

Calculates the digest over all handshake messages seen so far.

Definition at line 839 of file tls.c.

839 {
840 struct digest_algorithm *digest = tls->handshake_digest;
841 uint8_t ctx[ digest->ctxsize ];
842
843 memcpy ( ctx, tls->handshake_ctx, sizeof ( ctx ) );
844 digest_final ( digest, ctx, out );
845}
struct golan_eq_context ctx
Definition CIB_PRM.h:0
static void digest_final(struct digest_algorithm *digest, void *ctx, void *out)
Definition crypto.h:230
size_t ctxsize
Context size.
Definition crypto.h:23
uint8_t * handshake_ctx
Digest algorithm context used for handshake verification.
Definition tls.h:466
struct digest_algorithm * handshake_digest
Digest algorithm used for handshake verification.
Definition tls.h:464

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

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

◆ tls_uint24()

unsigned long tls_uint24 ( const tls24_t * field24)
inlinestatic

Extract 24-bit field value.

Parameters
field2424-bit field
Return values
valueField value

Definition at line 238 of file tls.c.

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

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

249 {
250
251 field24->high = ( value >> 16 );
252 field24->low = cpu_to_be16 ( value );
253}
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 261 of file tls.c.

261 {
262 return ( ( ! is_pending ( &tls->client.negotiation ) ) &&
263 ( ! is_pending ( &tls->server.negotiation ) ) );
264}
static int is_pending(struct pending_operation *pending)
Check if an operation is pending.
Definition pending.h:25
struct pending_operation negotiation
Security negotiation pending operation.
Definition tls.h:411
struct tls_server server
Server state.
Definition tls.h:481
struct tls_client client
Client state.
Definition tls.h:479
struct pending_operation negotiation
Security negotiation pending operation.
Definition tls.h:433

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

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

◆ tls_version()

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

Check for TLS version.

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

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

Definition at line 278 of file tls.c.

278 {
279 return ( ( TLS_VERSION_MIN >= version ) ||
280 ( tls->version >= version ) );
281}
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_prf(), tls_select_cipher(), tls_send_certificate_verify(), and tls_verify_dh_params().

◆ md5_sha1_init()

void md5_sha1_init ( void * ctx)
static

Initialise MD5+SHA1 algorithm.

Parameters
ctxMD5+SHA1 context

Definition at line 295 of file tls.c.

295 {
296 struct md5_sha1_context *context = ctx;
297
298 digest_init ( &md5_algorithm, context->md5 );
299 digest_init ( &sha1_algorithm, context->sha1 );
300}
static void digest_init(struct digest_algorithm *digest, void *ctx)
Definition crypto.h:219
struct digest_algorithm md5_algorithm
MD5 algorithm.
Definition md5.c:287
struct digest_algorithm sha1_algorithm
SHA-1 algorithm.
Definition sha1.c:258
An MD5+SHA1 context.
Definition tls.h:320
uint8_t sha1[SHA1_CTX_SIZE]
SHA-1 context.
Definition tls.h:324
uint8_t md5[MD5_CTX_SIZE]
MD5 context.
Definition tls.h:322

References ctx, digest_init(), md5_sha1_context::md5, md5_algorithm, md5_sha1_context::sha1, and sha1_algorithm.

◆ md5_sha1_update()

void md5_sha1_update ( void * ctx,
const void * data,
size_t len )
static

Accumulate data with MD5+SHA1 algorithm.

Parameters
ctxMD5+SHA1 context
dataData
lenLength of data

Definition at line 309 of file tls.c.

309 {
310 struct md5_sha1_context *context = ctx;
311
312 digest_update ( &md5_algorithm, context->md5, data, len );
313 digest_update ( &sha1_algorithm, context->sha1, data, len );
314}
static void digest_update(struct digest_algorithm *digest, void *ctx, const void *data, size_t len)
Definition crypto.h:224

References ctx, data, digest_update(), len, md5_sha1_context::md5, md5_algorithm, md5_sha1_context::sha1, and sha1_algorithm.

◆ md5_sha1_final()

void md5_sha1_final ( void * ctx,
void * out )
static

Generate MD5+SHA1 digest.

Parameters
ctxMD5+SHA1 context
outOutput buffer

Definition at line 322 of file tls.c.

322 {
323 struct md5_sha1_context *context = ctx;
324 struct md5_sha1_digest *digest = out;
325
326 digest_final ( &md5_algorithm, context->md5, digest->md5 );
327 digest_final ( &sha1_algorithm, context->sha1, digest->sha1 );
328}
An MD5+SHA1 digest.
Definition tls.h:331
uint8_t md5[MD5_DIGEST_SIZE]
MD5 digest.
Definition tls.h:333
uint8_t sha1[SHA1_DIGEST_SIZE]
SHA-1 digest.
Definition tls.h:335

References ctx, digest_final(), md5_sha1_context::md5, md5_sha1_digest::md5, md5_algorithm, out, md5_sha1_context::sha1, md5_sha1_digest::sha1, and sha1_algorithm.

◆ free_tls_session()

void free_tls_session ( struct refcnt * refcnt)
static

Free TLS session.

Parameters
refcntReference counter

Definition at line 360 of file tls.c.

360 {
361 struct tls_session *session =
363
364 /* Sanity check */
365 assert ( list_empty ( &session->conn ) );
366
367 /* Remove from list of sessions */
368 list_del ( &session->list );
369
370 /* Free dynamically-allocated resources */
371 x509_root_put ( session->root );
372 privkey_put ( session->key );
373 free ( session->ticket );
374
375 /* Free session */
376 free ( session );
377}
#define list_del(list)
Delete an entry from a list.
Definition list.h:120
#define list_empty(list)
Test whether a list is empty.
Definition list.h:137
static void privkey_put(struct private_key *key)
Drop reference to private key.
Definition privkey.h:42
static void(* free)(struct refcnt *refcnt))
Definition refcnt.h:55
#define container_of(ptr, type, field)
Get containing structure.
Definition stddef.h:36
A reference counter.
Definition refcnt.h:27
A TLS session.
Definition tls.h:342
struct private_key * key
Private key.
Definition tls.h:353
struct x509_root * root
Root of trust.
Definition tls.h:351
void * ticket
Session ticket.
Definition tls.h:360
struct list_head list
List of sessions.
Definition tls.h:346
static void x509_root_put(struct x509_root *root)
Drop reference to X.509 root certificate list.
Definition x509.h:404

References assert, tls_session::conn, container_of, free, tls_session::key, tls_session::list, list_del, list_empty, privkey_put(), tls_session::root, tls_session::ticket, and x509_root_put().

Referenced by tls_session().

◆ free_tls()

void free_tls ( struct refcnt * refcnt)
static

Free TLS connection.

Parameters
refcntReference counter

Definition at line 384 of file tls.c.

384 {
385 struct tls_connection *tls =
387 struct tls_session *session = tls->session;
388 struct io_buffer *iobuf;
389 struct io_buffer *tmp;
390
391 /* Free dynamically-allocated resources */
392 free ( tls->new_session_ticket );
393 tls_clear_cipher ( tls, &tls->tx.cipherspec.active );
394 tls_clear_cipher ( tls, &tls->tx.cipherspec.pending );
395 tls_clear_cipher ( tls, &tls->rx.cipherspec.active );
396 tls_clear_cipher ( tls, &tls->rx.cipherspec.pending );
397 free ( tls->server.exchange );
398 free ( tls->handshake_ctx );
399 list_for_each_entry_safe ( iobuf, tmp, &tls->rx.data, list ) {
400 list_del ( &iobuf->list );
401 free_iob ( iobuf );
402 }
403 free_iob ( tls->rx.handshake );
404 privkey_put ( tls->client.key );
405 x509_chain_put ( tls->client.chain );
406 x509_chain_put ( tls->server.chain );
407 x509_root_put ( tls->server.root );
408
409 /* Drop reference to session */
410 assert ( list_empty ( &tls->list ) );
411 ref_put ( &session->refcnt );
412
413 /* Free TLS structure itself */
414 free ( tls );
415}
unsigned long tmp
Definition linux_pci.h:65
#define list_for_each_entry_safe(pos, tmp, head, member)
Iterate over entries in a list, safe against deletion of the current entry.
Definition list.h:459
#define ref_put(refcnt)
Drop reference to object.
Definition refcnt.h:107
struct list_head list
List of which this buffer is a member.
Definition iobuf.h:45
struct tls_cipherspec pending
Next cipher specification.
Definition tls.h:279
struct private_key * key
Private key (if used)
Definition tls.h:407
struct x509_chain * chain
Certificate chain (if used)
Definition tls.h:409
struct tls_rx rx
Receive state.
Definition tls.h:477
void * new_session_ticket
New session ticket.
Definition tls.h:450
struct tls_cipherspec_pair cipherspec
Cipher specifications.
Definition tls.h:387
struct list_head data
List of received data buffers.
Definition tls.h:397
struct io_buffer * handshake
Received handshake fragment.
Definition tls.h:399
struct x509_root * root
Root of trust.
Definition tls.h:423
void * exchange
Server Key Exchange record (if any)
Definition tls.h:419
struct x509_chain * chain
Certificate chain.
Definition tls.h:425
struct refcnt refcnt
Reference counter.
Definition tls.h:344
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_server::exchange, free, free_iob(), tls_rx::handshake, tls_connection::handshake_ctx, tls_client::key, io_buffer::list, tls_connection::list, list_del, list_empty, list_for_each_entry_safe, tls_connection::new_session_ticket, tls_cipherspec_pair::pending, privkey_put(), ref_put, tls_session::refcnt, tls_server::root, tls_connection::rx, tls_connection::server, tls_connection::session, tls_clear_cipher(), tmp, tls_connection::tx, x509_chain_put(), and x509_root_put().

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

423 {
424
425 /* Send closure alert */
427
428 /* Remove pending operations, if applicable */
431 pending_put ( &tls->server.validation );
432
433 /* Remove process */
434 process_del ( &tls->tx.process );
435
436 /* Close all interfaces */
437 intf_shutdown ( &tls->cipherstream, rc );
438 intf_shutdown ( &tls->plainstream, rc );
439 intf_shutdown ( &tls->server.validator, rc );
440
441 /* Remove from session */
442 list_del ( &tls->list );
443 INIT_LIST_HEAD ( &tls->list );
444
445 /* Resume all other connections, in case we were the lead connection */
446 tls_tx_resume_all ( tls->session );
447}
void intf_shutdown(struct interface *intf, int rc)
Shut down an object interface.
Definition interface.c:279
#define INIT_LIST_HEAD(list)
Initialise a list head.
Definition list.h:46
void pending_put(struct pending_operation *pending)
Mark an operation as no longer pending.
Definition pending.c:59
void process_del(struct process *process)
Remove process from process list.
Definition process.c:80
struct interface plainstream
Plaintext stream.
Definition tls.h:455
struct pending_operation validation
Certificate validation pending operation.
Definition tls.h:431
struct interface validator
Certificate validator.
Definition tls.h:429
struct process process
Transmit process.
Definition tls.h:381
static int tls_send_alert(struct tls_connection *tls, unsigned int level, unsigned int description)
Transmit Alert record.
Definition tls.c:2014
static void tls_tx_resume_all(struct tls_session *session)
Resume TX state machine for all connections within a session.
Definition tls.c:1123
#define TLS_ALERT_CLOSE_NOTIFY
Definition tls.h:86
#define TLS_ALERT_WARNING
Definition tls.h:82

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

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

◆ tls_generate_random()

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

Generate random data.

Parameters
tlsTLS connection
dataBuffer to fill
lenLength of buffer
Return values
rcReturn status code

Definition at line 464 of file tls.c.

465 {
466 int rc;
467
468 /* Generate random bits with no additional input and without
469 * prediction resistance
470 */
471 if ( ( rc = rbg_generate ( NULL, 0, 0, data, len ) ) != 0 ) {
472 DBGC ( tls, "TLS %p could not generate random data: %s\n",
473 tls, strerror ( rc ) );
474 return rc;
475 }
476
477 return 0;
478}
int rbg_generate(const void *additional, size_t additional_len, int prediction_resist, void *data, size_t len)
Generate bits using RBG.
Definition rbg.c:117

References data, DBGC, len, NULL, rbg_generate(), rc, and strerror().

Referenced by add_tls(), tls_send_client_key_exchange_dhe(), tls_send_client_key_exchange_ecdhe(), tls_send_client_key_exchange_pubkey(), and tls_send_record().

◆ tls_hmac_update_va()

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

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

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

Definition at line 487 of file tls.c.

488 {
489 void *data;
490 size_t len;
491
492 while ( ( data = va_arg ( args, void * ) ) ) {
493 len = va_arg ( args, size_t );
494 hmac_update ( digest, ctx, data, len );
495 }
496}
static void hmac_update(struct digest_algorithm *digest, void *ctx, const void *data, size_t len)
Update HMAC.
Definition hmac.h:43
#define va_arg(ap, type)
Definition stdarg.h:9

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

Referenced by tls_p_hash_va().

◆ tls_p_hash_va()

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

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

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

Definition at line 509 of file tls.c.

513 {
514 uint8_t ctx[ hmac_ctxsize ( digest ) ];
515 uint8_t ctx_partial[ sizeof ( ctx ) ];
516 uint8_t a[digest->digestsize];
517 uint8_t out_tmp[digest->digestsize];
518 size_t frag_len = digest->digestsize;
519 va_list tmp;
520
521 DBGC2 ( tls, "TLS %p %s secret:\n", tls, digest->name );
522 DBGC2_HD ( tls, secret, secret_len );
523
524 /* Calculate A(1) */
525 hmac_init ( digest, ctx, secret, secret_len );
526 va_copy ( tmp, seeds );
527 tls_hmac_update_va ( digest, ctx, tmp );
528 va_end ( tmp );
529 hmac_final ( digest, ctx, a );
530 DBGC2 ( tls, "TLS %p %s A(1):\n", tls, digest->name );
531 DBGC2_HD ( tls, &a, sizeof ( a ) );
532
533 /* Generate as much data as required */
534 while ( out_len ) {
535 /* Calculate output portion */
536 hmac_init ( digest, ctx, secret, secret_len );
537 hmac_update ( digest, ctx, a, sizeof ( a ) );
538 memcpy ( ctx_partial, ctx, sizeof ( ctx_partial ) );
539 va_copy ( tmp, seeds );
540 tls_hmac_update_va ( digest, ctx, tmp );
541 va_end ( tmp );
542 hmac_final ( digest, ctx, out_tmp );
543
544 /* Copy output */
545 if ( frag_len > out_len )
546 frag_len = out_len;
547 memcpy ( out, out_tmp, frag_len );
548 DBGC2 ( tls, "TLS %p %s output:\n", tls, digest->name );
549 DBGC2_HD ( tls, out, frag_len );
550
551 /* Calculate A(i) */
552 hmac_final ( digest, ctx_partial, a );
553 DBGC2 ( tls, "TLS %p %s A(n):\n", tls, digest->name );
554 DBGC2_HD ( tls, &a, sizeof ( a ) );
555
556 out += frag_len;
557 out_len -= frag_len;
558 }
559}
#define DBGC2_HD(...)
Definition compiler.h:524
void hmac_init(struct digest_algorithm *digest, void *ctx, const void *key, size_t key_len)
Initialise HMAC.
Definition hmac.c:58
void hmac_final(struct digest_algorithm *digest, void *ctx, void *hmac)
Finalise HMAC.
Definition hmac.c:88
static size_t hmac_ctxsize(struct digest_algorithm *digest)
Calculate HMAC context size.
Definition hmac.h:29
#define va_copy(dest, src)
Definition stdarg.h:11
#define va_end(ap)
Definition stdarg.h:10
__builtin_va_list va_list
Definition stdarg.h:7
const char * name
Algorithm name.
Definition crypto.h:21
static void tls_hmac_update_va(struct digest_algorithm *digest, void *ctx, va_list args)
Update HMAC with a list of ( data, len ) pairs.
Definition tls.c:487

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

Referenced by tls_prf().

◆ tls_prf()

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

Generate secure pseudo-random data.

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

Definition at line 571 of file tls.c.

572 {
573 va_list seeds;
574 va_list tmp;
575 size_t subsecret_len;
576 const void *md5_secret;
577 const void *sha1_secret;
578 uint8_t buf[out_len];
579 unsigned int i;
580
581 va_start ( seeds, out_len );
582
583 if ( tls_version ( tls, TLS_VERSION_TLS_1_2 ) ) {
584 /* Use handshake digest PRF for TLSv1.2 and later */
585 tls_p_hash_va ( tls, tls->handshake_digest, secret, secret_len,
586 out, out_len, seeds );
587 } else {
588 /* Use combination of P_MD5 and P_SHA-1 for TLSv1.1
589 * and earlier
590 */
591
592 /* Split secret into two, with an overlap of up to one byte */
593 subsecret_len = ( ( secret_len + 1 ) / 2 );
594 md5_secret = secret;
595 sha1_secret = ( secret + secret_len - subsecret_len );
596
597 /* Calculate MD5 portion */
598 va_copy ( tmp, seeds );
599 tls_p_hash_va ( tls, &md5_algorithm, md5_secret,
600 subsecret_len, out, out_len, seeds );
601 va_end ( tmp );
602
603 /* Calculate SHA1 portion */
604 va_copy ( tmp, seeds );
605 tls_p_hash_va ( tls, &sha1_algorithm, sha1_secret,
606 subsecret_len, buf, out_len, seeds );
607 va_end ( tmp );
608
609 /* XOR the two portions together into the final output buffer */
610 for ( i = 0 ; i < out_len ; i++ )
611 *( ( uint8_t * ) out + i ) ^= buf[i];
612 }
613
614 va_end ( seeds );
615}
#define va_start(ap, last)
Definition stdarg.h:8
static void tls_p_hash_va(struct tls_connection *tls, struct digest_algorithm *digest, const void *secret, size_t secret_len, void *out, size_t out_len, va_list seeds)
Generate secure pseudo-random data using a single hash function.
Definition tls.c:509
static int tls_version(struct tls_connection *tls, unsigned int version)
Check for TLS version.
Definition tls.c:278
#define TLS_VERSION_TLS_1_2
TLS version 1.2.
Definition tls.h:48

References tls_connection::handshake_digest, md5_algorithm, out, sha1_algorithm, tls_p_hash_va(), tls_version(), TLS_VERSION_TLS_1_2, tmp, va_copy, va_end, and va_start.

◆ tls_generate_master_secret()

void tls_generate_master_secret ( struct tls_connection * tls,
const void * pre_master_secret,
size_t pre_master_secret_len )
static

Generate master secret.

Parameters
tlsTLS connection
pre_master_secretPre-master secret
pre_master_secret_lenLength of pre-master secret

The client and server random values must already be known.

Definition at line 647 of file tls.c.

649 {
650 struct digest_algorithm *digest = tls->handshake_digest;
651 uint8_t digest_out[ digest->digestsize ];
652
653 /* Generate handshake digest */
654 tls_verify_handshake ( tls, digest_out );
655
656 /* Show inputs */
657 DBGC ( tls, "TLS %p pre-master secret:\n", tls );
658 DBGC_HD ( tls, pre_master_secret, pre_master_secret_len );
659 DBGC ( tls, "TLS %p client random bytes:\n", tls );
660 DBGC_HD ( tls, &tls->client.random, sizeof ( tls->client.random ) );
661 DBGC ( tls, "TLS %p server random bytes:\n", tls );
662 DBGC_HD ( tls, &tls->server.random, sizeof ( tls->server.random ) );
663 DBGC ( tls, "TLS %p session hash:\n", tls );
664 DBGC_HD ( tls, digest_out, sizeof ( digest_out ) );
665
666 /* Generate master secret */
667 if ( tls->extended_master_secret ) {
668 tls_prf_label ( tls, pre_master_secret, pre_master_secret_len,
669 &tls->master_secret,
670 sizeof ( tls->master_secret ),
671 "extended master secret",
672 digest_out, sizeof ( digest_out ) );
673 } else {
674 tls_prf_label ( tls, pre_master_secret, pre_master_secret_len,
675 &tls->master_secret,
676 sizeof ( tls->master_secret ),
677 "master secret",
678 &tls->client.random,
679 sizeof ( tls->client.random ),
680 &tls->server.random,
681 sizeof ( tls->server.random ) );
682 }
683
684 /* Show output */
685 DBGC ( tls, "TLS %p generated %smaster secret:\n", tls,
686 ( tls->extended_master_secret ? "extended ": "" ) );
687 DBGC_HD ( tls, &tls->master_secret, sizeof ( tls->master_secret ) );
688}
#define DBGC_HD(...)
Definition compiler.h:507
struct tls_client_random random
Random bytes.
Definition tls.h:405
uint8_t master_secret[48]
Master secret.
Definition tls.h:462
int extended_master_secret
Extended master secret flag.
Definition tls.h:470
uint8_t random[32]
Random bytes.
Definition tls.h:417
#define tls_prf_label(tls, secret, secret_len, out, out_len, label,...)
Generate secure pseudo-random data.
Definition tls.c:627
static void tls_verify_handshake(struct tls_connection *tls, void *out)
Calculate handshake verification hash.
Definition tls.c:839

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

Referenced by tls_send_client_key_exchange_dhe(), tls_send_client_key_exchange_ecdhe(), and tls_send_client_key_exchange_pubkey().

◆ tls_generate_keys()

int tls_generate_keys ( struct tls_connection * tls)
static

Generate key material.

Parameters
tlsTLS connection

The master secret must already be known.

Definition at line 697 of file tls.c.

697 {
698 struct tls_cipherspec *tx_cipherspec = &tls->tx.cipherspec.pending;
699 struct tls_cipherspec *rx_cipherspec = &tls->rx.cipherspec.pending;
700 size_t hash_size = tx_cipherspec->suite->mac_len;
701 size_t key_size = tx_cipherspec->suite->key_len;
702 size_t iv_size = tx_cipherspec->suite->fixed_iv_len;
703 size_t total = ( 2 * ( hash_size + key_size + iv_size ) );
704 uint8_t key_block[total];
705 uint8_t *key;
706 int rc;
707
708 /* Generate key block */
709 tls_prf_label ( tls, &tls->master_secret, sizeof ( tls->master_secret ),
710 key_block, sizeof ( key_block ), "key expansion",
711 &tls->server.random, sizeof ( tls->server.random ),
712 &tls->client.random, sizeof ( tls->client.random ) );
713
714 /* Split key block into portions */
715 key = key_block;
716
717 /* TX MAC secret */
718 memcpy ( tx_cipherspec->mac_secret, key, hash_size );
719 DBGC ( tls, "TLS %p TX MAC secret:\n", tls );
720 DBGC_HD ( tls, key, hash_size );
721 key += hash_size;
722
723 /* RX MAC secret */
724 memcpy ( rx_cipherspec->mac_secret, key, hash_size );
725 DBGC ( tls, "TLS %p RX MAC secret:\n", tls );
726 DBGC_HD ( tls, key, hash_size );
727 key += hash_size;
728
729 /* TX key */
730 if ( ( rc = cipher_setkey ( tx_cipherspec->suite->cipher,
731 tx_cipherspec->cipher_ctx,
732 key, key_size ) ) != 0 ) {
733 DBGC ( tls, "TLS %p could not set TX key: %s\n",
734 tls, strerror ( rc ) );
735 return rc;
736 }
737 DBGC ( tls, "TLS %p TX key:\n", tls );
738 DBGC_HD ( tls, key, key_size );
739 key += key_size;
740
741 /* RX key */
742 if ( ( rc = cipher_setkey ( rx_cipherspec->suite->cipher,
743 rx_cipherspec->cipher_ctx,
744 key, key_size ) ) != 0 ) {
745 DBGC ( tls, "TLS %p could not set TX key: %s\n",
746 tls, strerror ( rc ) );
747 return rc;
748 }
749 DBGC ( tls, "TLS %p RX key:\n", tls );
750 DBGC_HD ( tls, key, key_size );
751 key += key_size;
752
753 /* TX initialisation vector */
754 memcpy ( tx_cipherspec->fixed_iv, key, iv_size );
755 DBGC ( tls, "TLS %p TX IV:\n", tls );
756 DBGC_HD ( tls, key, iv_size );
757 key += iv_size;
758
759 /* RX initialisation vector */
760 memcpy ( rx_cipherspec->fixed_iv, key, iv_size );
761 DBGC ( tls, "TLS %p RX IV:\n", tls );
762 DBGC_HD ( tls, key, iv_size );
763 key += iv_size;
764
765 assert ( ( key_block + total ) == key );
766
767 return 0;
768}
union @162305117151260234136356364136041353210355154177 key
Sense key.
Definition scsi.h:3
static int cipher_setkey(struct cipher_algorithm *cipher, void *ctx, const void *key, size_t keylen)
Definition crypto.h:235
uint8_t key_len
Key length.
Definition tls.h:217
void * mac_secret
MAC secret.
Definition tls.h:269

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

Referenced by tls_new_server_hello(), and tls_send_client_key_exchange().

◆ tls_clear_handshake()

void tls_clear_handshake ( struct tls_connection * tls)
static

Clear handshake digest algorithm.

Parameters
tlsTLS connection

Definition at line 782 of file tls.c.

782 {
783
784 /* Select null digest algorithm */
786
787 /* Free any existing context */
788 free ( tls->handshake_ctx );
789 tls->handshake_ctx = NULL;
790}
struct digest_algorithm digest_null
Definition crypto_null.c:49

References digest_null, free, tls_connection::handshake_ctx, tls_connection::handshake_digest, and NULL.

Referenced by add_tls(), and tls_select_handshake().

◆ tls_select_handshake()

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

Select handshake digest algorithm.

Parameters
tlsTLS connection
digestHandshake digest algorithm
Return values
rcReturn status code

Definition at line 799 of file tls.c.

800 {
801
802 /* Clear existing handshake digest */
803 tls_clear_handshake ( tls );
804
805 /* Allocate and initialise context */
806 tls->handshake_ctx = malloc ( digest->ctxsize );
807 if ( ! tls->handshake_ctx )
808 return -ENOMEM;
809 tls->handshake_digest = digest;
810 digest_init ( digest, tls->handshake_ctx );
811
812 return 0;
813}
#define ENOMEM
Not enough space.
Definition errno.h:535
void * malloc(size_t size)
Allocate memory.
Definition malloc.c:621
static void tls_clear_handshake(struct tls_connection *tls)
Clear handshake digest algorithm.
Definition tls.c:782

References digest_algorithm::ctxsize, digest_init(), ENOMEM, tls_connection::handshake_ctx, tls_connection::handshake_digest, malloc(), and tls_clear_handshake().

Referenced by tls_select_cipher().

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

824 {
825 struct digest_algorithm *digest = tls->handshake_digest;
826
827 digest_update ( digest, tls->handshake_ctx, data, len );
828 return 0;
829}

References data, digest_update(), tls_connection::handshake_ctx, tls_connection::handshake_digest, and len.

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

◆ tls_find_cipher_suite()

struct tls_cipher_suite * tls_find_cipher_suite ( unsigned int cipher_suite)
static

Identify cipher suite.

Parameters
cipher_suiteCipher suite specification
Return values
suiteCipher suite, or NULL

Definition at line 872 of file tls.c.

872 {
873 struct tls_cipher_suite *suite;
874
875 /* Identify cipher suite */
877 if ( suite->code == cipher_suite )
878 return suite;
879 }
880
881 return NULL;
882}
uint16_t code
Numeric code (in network-endian order)
Definition tls.h:215
#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:227

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

Referenced by tls_select_cipher().

◆ tls_clear_cipher() [2/2]

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

Clear cipher suite.

Parameters
cipherspecTLS cipher specification

Definition at line 889 of file tls.c.

890 {
891
892 free ( cipherspec->dynamic );
893 memset ( cipherspec, 0, sizeof ( *cipherspec ) );
894 cipherspec->suite = &tls_cipher_suite_null;
895}
void * dynamic
Dynamically-allocated storage.
Definition tls.h:265
struct tls_cipher_suite tls_cipher_suite_null
Null cipher suite.
Definition tls.c:855

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

◆ tls_set_cipher()

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

Set cipher suite.

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

Definition at line 905 of file tls.c.

907 {
908 struct cipher_algorithm *cipher = suite->cipher;
909 size_t total;
910 void *dynamic;
911
912 /* Clear out old cipher contents, if any */
913 tls_clear_cipher ( tls, cipherspec );
914
915 /* Allocate dynamic storage */
916 total = ( cipher->ctxsize + suite->mac_len + suite->fixed_iv_len );
917 dynamic = zalloc ( total );
918 if ( ! dynamic ) {
919 DBGC ( tls, "TLS %p could not allocate %zd bytes for crypto "
920 "context\n", tls, total );
921 return -ENOMEM_CONTEXT;
922 }
923
924 /* Assign storage */
925 cipherspec->dynamic = dynamic;
926 cipherspec->cipher_ctx = dynamic; dynamic += cipher->ctxsize;
927 cipherspec->mac_secret = dynamic; dynamic += suite->mac_len;
928 cipherspec->fixed_iv = dynamic; dynamic += suite->fixed_iv_len;
929 assert ( ( cipherspec->dynamic + total ) == dynamic );
930
931 /* Store parameters */
932 cipherspec->suite = suite;
933
934 return 0;
935}
void * zalloc(size_t size)
Allocate cleared memory.
Definition malloc.c:662
size_t ctxsize
Context size.
Definition crypto.h:55
#define ENOMEM_CONTEXT
Definition tls.c:118

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

Referenced by tls_select_cipher().

◆ tls_select_cipher()

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

Select next cipher suite.

Parameters
tlsTLS connection
cipher_suiteCipher suite specification
Return values
rcReturn status code

Definition at line 944 of file tls.c.

945 {
946 struct tls_cipher_suite *suite;
947 struct digest_algorithm *digest;
948 int rc;
949
950 /* Identify cipher suite */
951 suite = tls_find_cipher_suite ( cipher_suite );
952 if ( ! suite ) {
953 DBGC ( tls, "TLS %p does not support cipher %04x\n",
954 tls, ntohs ( cipher_suite ) );
955 return -ENOTSUP_CIPHER;
956 }
957
958 /* Set handshake digest algorithm */
959 digest = ( tls_version ( tls, TLS_VERSION_TLS_1_2 ) ?
960 suite->handshake : &md5_sha1_algorithm );
961 if ( ( rc = tls_select_handshake ( tls, digest ) ) != 0 )
962 return rc;
963
964 /* Set ciphers */
965 if ( ( rc = tls_set_cipher ( tls, &tls->tx.cipherspec.pending,
966 suite ) ) != 0 )
967 return rc;
968 if ( ( rc = tls_set_cipher ( tls, &tls->rx.cipherspec.pending,
969 suite ) ) != 0 )
970 return rc;
971
972 DBGC ( tls, "TLS %p selected %s-%s-%s-%d-%s\n", tls,
973 suite->exchange->name, suite->pubkey->name,
974 suite->cipher->name, ( suite->key_len * 8 ),
975 suite->digest->name );
976
977 return 0;
978}
#define ntohs(value)
Definition byteswap.h:137
const char * name
Algorithm name.
Definition crypto.h:53
const char * name
Algorithm name.
Definition crypto.h:124
struct pubkey_algorithm * pubkey
Public-key encryption algorithm.
Definition tls.h:207
struct tls_key_exchange_algorithm * exchange
Key exchange algorithm.
Definition tls.h:205
struct digest_algorithm * handshake
Handshake digest algorithm (for TLSv1.2 and above)
Definition tls.h:213
const char * name
Algorithm name.
Definition tls.h:192
#define ENOTSUP_CIPHER
Definition tls.c:146
static int tls_select_handshake(struct tls_connection *tls, struct digest_algorithm *digest)
Select handshake digest algorithm.
Definition tls.c:799
static int tls_set_cipher(struct tls_connection *tls, struct tls_cipherspec *cipherspec, struct tls_cipher_suite *suite)
Set cipher suite.
Definition tls.c:905
static struct tls_cipher_suite * tls_find_cipher_suite(unsigned int cipher_suite)
Identify cipher suite.
Definition tls.c:872
static struct digest_algorithm md5_sha1_algorithm
Hybrid MD5+SHA1 digest algorithm.
Definition tls.c:331

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

Referenced by tls_new_server_hello().

◆ tls_change_cipher()

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

Activate next cipher suite.

Parameters
tlsTLS connection
pairCipher specification pair
Return values
rcReturn status code

Definition at line 987 of file tls.c.

988 {
989
990 /* Sanity check */
991 if ( pair->pending.suite == &tls_cipher_suite_null ) {
992 DBGC ( tls, "TLS %p refusing to use null cipher\n", tls );
993 return -ENOTSUP_NULL;
994 }
995
996 tls_clear_cipher ( tls, &pair->active );
997 memswap ( &pair->active, &pair->pending, sizeof ( pair->active ) );
998 return 0;
999}
void * memswap(void *first, void *second, size_t len)
Swap memory regions.
Definition string.c:154
#define ENOTSUP_NULL
Definition tls.c:150

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

Referenced by tls_new_change_cipher(), and tls_tx_step().

◆ tls_signature_hash_algorithm()

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

Find TLS signature and hash algorithm.

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

Definition at line 1020 of file tls.c.

1021 {
1022 struct tls_signature_hash_algorithm *sig_hash;
1023
1024 /* Identify signature and hash algorithm */
1026 if ( ( sig_hash->pubkey == pubkey ) &&
1027 ( sig_hash->digest == digest ) ) {
1028 return sig_hash;
1029 }
1030 }
1031
1032 return NULL;
1033}
A TLS signature algorithm.
Definition tls.h:291
struct pubkey_algorithm * pubkey
Public-key algorithm.
Definition tls.h:295
struct digest_algorithm * digest
Digest algorithm.
Definition tls.h:293
#define TLS_SIG_HASH_ALGORITHMS
TLS signature hash algorithm table.
Definition tls.h:305

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

struct pubkey_algorithm * tls_signature_hash_pubkey ( struct tls_signature_hash_id code)
static

Find TLS signature algorithm.

Parameters
codeSignature and hash algorithm identifier
Return values
pubkeyPublic key algorithm, or NULL

Definition at line 1042 of file tls.c.

1042 {
1043 struct tls_signature_hash_algorithm *sig_hash;
1044
1045 /* Identify signature and hash algorithm */
1047 if ( sig_hash->code.signature == code.signature )
1048 return sig_hash->pubkey;
1049 }
1050
1051 return NULL;
1052}
static unsigned int code
Response code.
Definition hyperv.h:26
struct tls_signature_hash_id code
Numeric code.
Definition tls.h:297
uint8_t signature
Signature algorithm.
Definition tls.h:287

References code, tls_signature_hash_algorithm::code, for_each_table_entry, NULL, tls_signature_hash_algorithm::pubkey, tls_signature_hash_id::signature, and TLS_SIG_HASH_ALGORITHMS.

Referenced by tls_verify_dh_params().

◆ tls_signature_hash_digest()

struct digest_algorithm * tls_signature_hash_digest ( struct tls_signature_hash_id code)
static

Find TLS hash algorithm.

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

Definition at line 1061 of file tls.c.

1061 {
1062 struct tls_signature_hash_algorithm *sig_hash;
1063
1064 /* Identify signature and hash algorithm */
1066 if ( sig_hash->code.hash == code.hash )
1067 return sig_hash->digest;
1068 }
1069
1070 return NULL;
1071}
uint8_t hash
Hash algorithm.
Definition tls.h:285

References code, tls_signature_hash_algorithm::code, tls_signature_hash_algorithm::digest, for_each_table_entry, tls_signature_hash_id::hash, NULL, and TLS_SIG_HASH_ALGORITHMS.

Referenced by tls_verify_dh_params().

◆ tls_find_named_curve()

struct tls_named_curve * tls_find_named_curve ( unsigned int named_curve)
static

Identify named curve.

Parameters
named_curveNamed curve specification
Return values
curveNamed curve, or NULL

Definition at line 1090 of file tls.c.

1090 {
1091 struct tls_named_curve *curve;
1092
1093 /* Identify named curve */
1095 if ( curve->code == named_curve )
1096 return curve;
1097 }
1098
1099 return NULL;
1100}
A TLS named curve.
Definition tls.h:241
struct elliptic_curve * curve
Elliptic curve.
Definition tls.h:243
#define TLS_NAMED_CURVES
TLS named curve table.
Definition tls.h:253

References tls_named_curve::curve, for_each_table_entry, NULL, and TLS_NAMED_CURVES.

Referenced by tls_send_client_key_exchange_ecdhe().

◆ tls_tx_resume()

void tls_tx_resume ( struct tls_connection * tls)
static

Resume TX state machine.

Parameters
tlsTLS connection

Definition at line 1114 of file tls.c.

1114 {
1115 process_add ( &tls->tx.process );
1116}
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 1135 of file tls.c.

1135 {
1136
1137 /* Sanity check */
1138 assert ( ! tls->tx.pending );
1139 assert ( ! is_pending ( &tls->client.negotiation ) );
1140 assert ( ! is_pending ( &tls->server.negotiation ) );
1141 assert ( ! is_pending ( &tls->server.validation ) );
1142
1143 /* (Re)start negotiation */
1145 tls_tx_resume ( tls );
1146 pending_get ( &tls->client.negotiation );
1147 pending_get ( &tls->server.negotiation );
1148}
void pending_get(struct pending_operation *pending)
Mark an operation as pending.
Definition pending.c:46
unsigned int pending
Pending transmissions.
Definition tls.h:379
@ TLS_TX_CLIENT_HELLO
Definition tls.h:181

References assert, 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_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 1158 of file tls.c.

1159 {
1160
1161 /* Send record */
1163}

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

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

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

1175 {
1176 struct tls_session *session = tls->session;
1177 size_t name_len = strlen ( session->name );
1178 struct {
1179 uint16_t type;
1180 uint16_t len;
1181 struct {
1182 uint16_t len;
1183 struct {
1184 uint8_t type;
1185 uint16_t len;
1186 uint8_t name[name_len];
1187 } __attribute__ (( packed )) list[1];
1188 } __attribute__ (( packed )) data;
1189 } __attribute__ (( packed )) *server_name_ext;
1190 struct {
1191 uint16_t type;
1192 uint16_t len;
1193 struct {
1194 uint8_t max;
1195 } __attribute__ (( packed )) data;
1196 } __attribute__ (( packed )) *max_fragment_length_ext;
1197 struct {
1198 uint16_t type;
1199 uint16_t len;
1200 struct {
1201 uint16_t len;
1204 } __attribute__ (( packed )) data;
1205 } __attribute__ (( packed )) *signature_algorithms_ext;
1206 struct {
1207 uint16_t type;
1208 uint16_t len;
1209 struct {
1210 uint8_t len;
1212 sizeof ( tls->verify.client ) :0 ];
1213 } __attribute__ (( packed )) data;
1214 } __attribute__ (( packed )) *renegotiation_info_ext;
1215 struct {
1216 uint16_t type;
1217 uint16_t len;
1218 struct {
1219 uint8_t data[session->ticket_len];
1220 } __attribute__ (( packed )) data;
1221 } __attribute__ (( packed )) *session_ticket_ext;
1222 struct {
1223 uint16_t type;
1224 uint16_t len;
1225 struct {
1226 uint16_t len;
1228 } __attribute__ (( packed )) data;
1229 } __attribute__ (( packed )) *named_curve_ext;
1230 struct {
1231 uint16_t type;
1232 uint16_t len;
1233 } __attribute__ (( packed )) *extended_master_secret_ext;
1234 struct {
1235 typeof ( *server_name_ext ) server_name;
1236 typeof ( *max_fragment_length_ext ) max_fragment_length;
1237 typeof ( *signature_algorithms_ext ) signature_algorithms;
1238 typeof ( *renegotiation_info_ext ) renegotiation_info;
1239 typeof ( *session_ticket_ext ) session_ticket;
1240 typeof ( *extended_master_secret_ext ) extended_master_secret;
1241 typeof ( *named_curve_ext )
1242 named_curve[TLS_NUM_NAMED_CURVES ? 1 : 0];
1243 } __attribute__ (( packed )) *extensions;
1244 struct {
1245 uint32_t type_length;
1247 uint8_t random[32];
1248 uint8_t session_id_len;
1249 uint8_t session_id[tls->session_id_len];
1250 uint16_t cipher_suite_len;
1251 uint16_t cipher_suites[TLS_NUM_CIPHER_SUITES];
1252 uint8_t compression_methods_len;
1253 uint8_t compression_methods[1];
1254 uint16_t extensions_len;
1255 typeof ( *extensions ) extensions;
1256 } __attribute__ (( packed )) hello;
1257 struct tls_cipher_suite *suite;
1258 struct tls_signature_hash_algorithm *sighash;
1259 struct tls_named_curve *curve;
1260 unsigned int i;
1261
1262 /* Construct record */
1263 memset ( &hello, 0, sizeof ( hello ) );
1264 hello.type_length = ( cpu_to_le32 ( TLS_CLIENT_HELLO ) |
1265 htonl ( sizeof ( hello ) -
1266 sizeof ( hello.type_length ) ) );
1267 hello.version = htons ( TLS_VERSION_MAX );
1268 memcpy ( &hello.random, &tls->client.random, sizeof ( hello.random ) );
1269 hello.session_id_len = tls->session_id_len;
1270 memcpy ( hello.session_id, tls->session_id,
1271 sizeof ( hello.session_id ) );
1272 hello.cipher_suite_len = htons ( sizeof ( hello.cipher_suites ) );
1273 i = 0 ; for_each_table_entry ( suite, TLS_CIPHER_SUITES )
1274 hello.cipher_suites[i++] = suite->code;
1275 hello.compression_methods_len = sizeof ( hello.compression_methods );
1276 hello.extensions_len = htons ( sizeof ( hello.extensions ) );
1277 extensions = &hello.extensions;
1278
1279 /* Construct server name extension */
1280 server_name_ext = &extensions->server_name;
1281 server_name_ext->type = htons ( TLS_SERVER_NAME );
1282 server_name_ext->len = htons ( sizeof ( server_name_ext->data ) );
1283 server_name_ext->data.len
1284 = htons ( sizeof ( server_name_ext->data.list ) );
1285 server_name_ext->data.list[0].type = TLS_SERVER_NAME_HOST_NAME;
1286 server_name_ext->data.list[0].len
1287 = htons ( sizeof ( server_name_ext->data.list[0].name ) );
1288 memcpy ( server_name_ext->data.list[0].name, session->name,
1289 sizeof ( server_name_ext->data.list[0].name ) );
1290
1291 /* Construct maximum fragment length extension */
1292 max_fragment_length_ext = &extensions->max_fragment_length;
1293 max_fragment_length_ext->type = htons ( TLS_MAX_FRAGMENT_LENGTH );
1294 max_fragment_length_ext->len
1295 = htons ( sizeof ( max_fragment_length_ext->data ) );
1296 max_fragment_length_ext->data.max = TLS_MAX_FRAGMENT_LENGTH_VALUE;
1297
1298 /* Construct supported signature algorithms extension */
1299 signature_algorithms_ext = &extensions->signature_algorithms;
1300 signature_algorithms_ext->type = htons ( TLS_SIGNATURE_ALGORITHMS );
1301 signature_algorithms_ext->len
1302 = htons ( sizeof ( signature_algorithms_ext->data ) );
1303 signature_algorithms_ext->data.len
1304 = htons ( sizeof ( signature_algorithms_ext->data.code ) );
1306 signature_algorithms_ext->data.code[i++] = sighash->code;
1307
1308 /* Construct renegotiation information extension */
1309 renegotiation_info_ext = &extensions->renegotiation_info;
1310 renegotiation_info_ext->type = htons ( TLS_RENEGOTIATION_INFO );
1311 renegotiation_info_ext->len
1312 = htons ( sizeof ( renegotiation_info_ext->data ) );
1313 renegotiation_info_ext->data.len
1314 = sizeof ( renegotiation_info_ext->data.data );
1315 memcpy ( renegotiation_info_ext->data.data, tls->verify.client,
1316 sizeof ( renegotiation_info_ext->data.data ) );
1317
1318 /* Construct session ticket extension */
1319 session_ticket_ext = &extensions->session_ticket;
1320 session_ticket_ext->type = htons ( TLS_SESSION_TICKET );
1321 session_ticket_ext->len
1322 = htons ( sizeof ( session_ticket_ext->data ) );
1323 memcpy ( session_ticket_ext->data.data, session->ticket,
1324 sizeof ( session_ticket_ext->data.data ) );
1325
1326 /* Construct extended master secret extension */
1327 extended_master_secret_ext = &extensions->extended_master_secret;
1328 extended_master_secret_ext->type
1330 extended_master_secret_ext->len = 0;
1331
1332 /* Construct named curves extension, if applicable */
1333 if ( sizeof ( extensions->named_curve ) ) {
1334 named_curve_ext = &extensions->named_curve[0];
1335 named_curve_ext->type = htons ( TLS_NAMED_CURVE );
1336 named_curve_ext->len
1337 = htons ( sizeof ( named_curve_ext->data ) );
1338 named_curve_ext->data.len
1339 = htons ( sizeof ( named_curve_ext->data.code ) );
1341 named_curve_ext->data.code[i++] = curve->code;
1342 }
1343
1344 return action ( tls, &hello, sizeof ( hello ) );
1345}
typeof(acpi_finder=acpi_find)
ACPI table finder.
Definition acpi.c:48
unsigned short uint16_t
Definition stdint.h:11
unsigned int uint32_t
Definition stdint.h:12
#define max(x, y)
Definition ath.h:41
#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
size_t strlen(const char *src)
Get length of string.
Definition string.c:244
struct tls_verify_data verify
Verification data.
Definition tls.h:472
size_t session_id_len
Length of session ID.
Definition tls.h:448
uint8_t session_id[32]
Session ID.
Definition tls.h:446
int secure_renegotiation
Secure renegotiation flag.
Definition tls.h:468
const char * name
Server name.
Definition tls.h:349
size_t ticket_len
Length of session ticket.
Definition tls.h:362
A TLS signature and hash algorithm identifier.
Definition tls.h:283
uint8_t client[12]
Client verification data.
Definition tls.h:168
#define TLS_NUM_CIPHER_SUITES
Number of supported cipher suites.
Definition tls.c:863
#define TLS_NUM_NAMED_CURVES
Number of supported named curves.
Definition tls.c:1081
#define TLS_NUM_SIG_HASH_ALGORITHMS
Number of supported signature and hash algorithms.
Definition tls.c:1009
#define TLS_EXTENDED_MASTER_SECRET
Definition tls.h:149
#define TLS_VERSION_MAX
Maximum supported TLS version.
Definition tls.h:51
#define TLS_RENEGOTIATION_INFO
Definition tls.h:155
#define TLS_MAX_FRAGMENT_LENGTH_VALUE
Advertised maximum fragment length.
Definition tls.h:485
#define TLS_CLIENT_HELLO
Definition tls.h:70
#define TLS_SERVER_NAME
Definition tls.h:129
#define TLS_SERVER_NAME_HOST_NAME
Definition tls.h:130
#define TLS_MAX_FRAGMENT_LENGTH
Definition tls.h:133
#define TLS_NAMED_CURVE
Definition tls.h:140
#define TLS_SESSION_TICKET
Definition tls.h:152
#define TLS_SIGNATURE_ALGORITHMS
Definition tls.h:146

References __attribute__, tls_connection::client, tls_verify_data::client, code, tls_cipher_suite::code, tls_signature_hash_algorithm::code, cpu_to_le32, tls_named_curve::curve, data, for_each_table_entry, hello, htonl, htons, len, tls_session::list, max, memcpy(), memset(), name, tls_session::name, random(), tls_client::random, tls_connection::secure_renegotiation, tls_connection::session, tls_connection::session_id, tls_connection::session_id_len, strlen(), tls_session::ticket, tls_session::ticket_len, TLS_CIPHER_SUITES, TLS_CLIENT_HELLO, TLS_EXTENDED_MASTER_SECRET, TLS_MAX_FRAGMENT_LENGTH, TLS_MAX_FRAGMENT_LENGTH_VALUE, TLS_NAMED_CURVE, TLS_NAMED_CURVES, TLS_NUM_CIPHER_SUITES, TLS_NUM_NAMED_CURVES, 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 1353 of file tls.c.

1353 {
1354
1355 return tls_client_hello ( tls, tls_send_handshake );
1356}
static int tls_send_handshake(struct tls_connection *tls, const void *data, size_t len)
Transmit Handshake record.
Definition tls.c:1158
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:1172

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

1364 {
1365 struct {
1367 uint8_t data[0];
1368 } __attribute__ (( packed )) *certificate;
1369 struct {
1370 uint32_t type_length;
1372 typeof ( *certificate ) certificates[0];
1373 } __attribute__ (( packed )) *certificates;
1374 struct x509_link *link;
1375 struct x509_certificate *cert;
1376 struct io_buffer *iobuf;
1377 size_t len;
1378
1379 /* Calculate length of client certificates */
1380 len = 0;
1382 cert = link->cert;
1383 len += ( sizeof ( *certificate ) + cert->raw.len );
1384 DBGC ( tls, "TLS %p sending client certificate %s\n",
1385 tls, x509_name ( cert ) );
1386 }
1387
1388 /* Allocate storage for Certificate record (which may be too
1389 * large for the stack).
1390 */
1391 iobuf = tls_alloc_iob ( tls, ( sizeof ( *certificates ) + len ) );
1392 if ( ! iobuf )
1393 return -ENOMEM_CERTIFICATE;
1394
1395 /* Populate record */
1396 certificates = iob_put ( iobuf, sizeof ( *certificates ) );
1397 certificates->type_length =
1399 htonl ( sizeof ( *certificates ) + len -
1400 sizeof ( certificates->type_length ) ) );
1401 tls_set_uint24 ( &certificates->length, len );
1403 cert = link->cert;
1404 certificate = iob_put ( iobuf, sizeof ( *certificate ) );
1405 tls_set_uint24 ( &certificate->length, cert->raw.len );
1406 memcpy ( iob_put ( iobuf, cert->raw.len ), cert->raw.data,
1407 cert->raw.len );
1408 }
1409
1410 /* Transmit record */
1411 return tls_send_record ( tls, TLS_TYPE_HANDSHAKE,
1412 iob_disown ( iobuf ) );
1413}
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:223
An X.509 certificate.
Definition x509.h:216
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:122
static void tls_set_uint24(tls24_t *field24, unsigned long value)
Set 24-bit field value.
Definition tls.c:249
#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, 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_pubkey()

int tls_send_client_key_exchange_pubkey ( struct tls_connection * tls)
static

Transmit Client Key Exchange record using public key exchange.

Parameters
tlsTLS connection
Return values
rcReturn status code

Definition at line 1421 of file tls.c.

1421 {
1422 struct tls_cipherspec *cipherspec = &tls->tx.cipherspec.pending;
1423 struct pubkey_algorithm *pubkey = cipherspec->suite->pubkey;
1424 struct {
1426 uint8_t random[46];
1427 } __attribute__ (( packed )) pre_master_secret;
1428 struct asn1_cursor cursor = {
1429 .data = &pre_master_secret,
1430 .len = sizeof ( pre_master_secret ),
1431 };
1432 struct asn1_builder builder = { NULL, 0 };
1433 int rc;
1434
1435 /* Generate pre-master secret */
1436 pre_master_secret.version = htons ( TLS_VERSION_MAX );
1437 if ( ( rc = tls_generate_random ( tls, &pre_master_secret.random,
1438 ( sizeof ( pre_master_secret.random ) ) ) ) != 0 ) {
1439 goto err_random;
1440 }
1441
1442 /* Encrypt pre-master secret using server's public key */
1443 if ( ( rc = pubkey_encrypt ( pubkey, &tls->server.key, &cursor,
1444 &builder ) ) != 0 ) {
1445 DBGC ( tls, "TLS %p could not encrypt pre-master secret: %s\n",
1446 tls, strerror ( rc ) );
1447 goto err_encrypt;
1448 }
1449
1450 /* Construct Client Key Exchange record */
1451 {
1452 struct {
1453 uint32_t type_length;
1454 uint16_t encrypted_pre_master_secret_len;
1455 } __attribute__ (( packed )) header;
1456
1457 header.type_length =
1459 htonl ( builder.len + sizeof ( header ) -
1460 sizeof ( header.type_length ) ) );
1461 header.encrypted_pre_master_secret_len = htons ( builder.len );
1462
1463 if ( ( rc = asn1_prepend_raw ( &builder, &header,
1464 sizeof ( header ) ) ) != 0 ) {
1465 DBGC ( tls, "TLS %p could not construct Client Key "
1466 "Exchange: %s\n", tls, strerror ( rc ) );
1467 goto err_prepend;
1468 }
1469 }
1470
1471 /* Transmit Client Key Exchange record */
1472 if ( ( rc = tls_send_handshake ( tls, builder.data,
1473 builder.len ) ) != 0 ) {
1474 goto err_send;
1475 }
1476
1477 /* Generate master secret */
1478 tls_generate_master_secret ( tls, &pre_master_secret,
1479 sizeof ( pre_master_secret ) );
1480
1481 err_random:
1482 err_encrypt:
1483 err_prepend:
1484 err_send:
1485 free ( builder.data );
1486 return rc;
1487}
int asn1_prepend_raw(struct asn1_builder *builder, const void *data, size_t len)
Prepend raw data to ASN.1 builder.
Definition asn1.c:949
struct ena_llq_option header
Header locations.
Definition ena.h:5
static int pubkey_encrypt(struct pubkey_algorithm *pubkey, const struct asn1_cursor *key, const struct asn1_cursor *plaintext, struct asn1_builder *ciphertext)
Definition crypto.h:287
An ASN.1 object builder.
Definition asn1.h:29
void * data
Data.
Definition asn1.h:36
size_t len
Length of data.
Definition asn1.h:38
An ASN.1 object cursor.
Definition asn1.h:21
A public key algorithm.
Definition crypto.h:122
struct asn1_cursor key
Public key (within server certificate)
Definition tls.h:427
static void tls_generate_master_secret(struct tls_connection *tls, const void *pre_master_secret, size_t pre_master_secret_len)
Generate master secret.
Definition tls.c:647
#define TLS_CLIENT_KEY_EXCHANGE
Definition tls.h:78

References __attribute__, asn1_prepend_raw(), tls_tx::cipherspec, cpu_to_le32, asn1_builder::data, DBGC, free, header, htonl, htons, tls_server::key, asn1_builder::len, NULL, tls_cipherspec_pair::pending, tls_cipher_suite::pubkey, pubkey_encrypt(), random(), rc, tls_connection::server, strerror(), tls_cipherspec::suite, TLS_CLIENT_KEY_EXCHANGE, tls_generate_master_secret(), tls_generate_random(), tls_send_handshake(), TLS_VERSION_MAX, tls_connection::tx, and version.

◆ tls_verify_dh_params()

int tls_verify_dh_params ( struct tls_connection * tls,
size_t param_len )
static

Verify Diffie-Hellman parameter signature.

Parameters
tlsTLS connection
param_lenDiffie-Hellman parameter length
Return values
rcReturn status code

Definition at line 1502 of file tls.c.

1503 {
1504 struct tls_cipherspec *cipherspec = &tls->tx.cipherspec.pending;
1505 struct pubkey_algorithm *pubkey;
1506 struct digest_algorithm *digest;
1507 int use_sig_hash = tls_version ( tls, TLS_VERSION_TLS_1_2 );
1508 const struct {
1509 struct tls_signature_hash_id sig_hash[use_sig_hash];
1510 uint16_t signature_len;
1511 uint8_t signature[0];
1512 } __attribute__ (( packed )) *sig;
1513 struct asn1_cursor signature;
1514 const void *data;
1515 size_t remaining;
1516 int rc;
1517
1518 /* Signature follows parameters */
1519 assert ( param_len <= tls->server.exchange_len );
1520 data = ( tls->server.exchange + param_len );
1521 remaining = ( tls->server.exchange_len - param_len );
1522
1523 /* Parse signature from ServerKeyExchange */
1524 sig = data;
1525 if ( ( sizeof ( *sig ) > remaining ) ||
1526 ( ntohs ( sig->signature_len ) > ( remaining -
1527 sizeof ( *sig ) ) ) ) {
1528 DBGC ( tls, "TLS %p received underlength ServerKeyExchange\n",
1529 tls );
1530 DBGC_HDA ( tls, 0, tls->server.exchange,
1531 tls->server.exchange_len );
1532 return -EINVAL_KEY_EXCHANGE;
1533 }
1534 signature.data = sig->signature;
1535 signature.len = ntohs ( sig->signature_len );
1536
1537 /* Identify signature and hash algorithm */
1538 if ( use_sig_hash ) {
1539 pubkey = tls_signature_hash_pubkey ( sig->sig_hash[0] );
1540 digest = tls_signature_hash_digest ( sig->sig_hash[0] );
1541 if ( ( ! pubkey ) || ( ! digest ) ) {
1542 DBGC ( tls, "TLS %p ServerKeyExchange unsupported "
1543 "signature and hash algorithm\n", tls );
1544 return -ENOTSUP_SIG_HASH;
1545 }
1546 if ( pubkey != cipherspec->suite->pubkey ) {
1547 DBGC ( tls, "TLS %p ServerKeyExchange incorrect "
1548 "signature algorithm %s (expected %s)\n", tls,
1549 pubkey->name, cipherspec->suite->pubkey->name );
1550 return -EPERM_KEY_EXCHANGE;
1551 }
1552 } else {
1553 pubkey = cipherspec->suite->pubkey;
1554 digest = &md5_sha1_algorithm;
1555 }
1556
1557 /* Verify signature */
1558 {
1559 uint8_t ctx[digest->ctxsize];
1560 uint8_t hash[digest->digestsize];
1561
1562 /* Calculate digest */
1563 digest_init ( digest, ctx );
1564 digest_update ( digest, ctx, &tls->client.random,
1565 sizeof ( tls->client.random ) );
1566 digest_update ( digest, ctx, tls->server.random,
1567 sizeof ( tls->server.random ) );
1568 digest_update ( digest, ctx, tls->server.exchange, param_len );
1569 digest_final ( digest, ctx, hash );
1570
1571 /* Verify signature */
1572 if ( ( rc = pubkey_verify ( pubkey, &tls->server.key, digest,
1573 hash, &signature ) ) != 0 ) {
1574 DBGC ( tls, "TLS %p ServerKeyExchange failed "
1575 "verification\n", tls );
1576 DBGC_HDA ( tls, 0, tls->server.exchange,
1577 tls->server.exchange_len );
1578 return -EPERM_KEY_EXCHANGE;
1579 }
1580 }
1581
1582 return 0;
1583}
u8 sig
Definition CIB_PRM.h:15
u8 signature
CPU signature.
Definition CIB_PRM.h:7
pseudo_bit_t hash[0x00010]
Definition arbel.h:2
#define DBGC_HDA(...)
Definition compiler.h:506
static int pubkey_verify(struct pubkey_algorithm *pubkey, const struct asn1_cursor *key, struct digest_algorithm *digest, const void *value, const struct asn1_cursor *signature)
Definition crypto.h:308
size_t exchange_len
Server Key Exchange record length.
Definition tls.h:421
static struct pubkey_algorithm * tls_signature_hash_pubkey(struct tls_signature_hash_id code)
Find TLS signature algorithm.
Definition tls.c:1042
#define EINVAL_KEY_EXCHANGE
Definition tls.c:110
#define EPERM_KEY_EXCHANGE
Definition tls.c:182
static struct digest_algorithm * tls_signature_hash_digest(struct tls_signature_hash_id code)
Find TLS hash algorithm.
Definition tls.c:1061
#define ENOTSUP_SIG_HASH
Definition tls.c:154

References __attribute__, assert, tls_tx::cipherspec, tls_connection::client, ctx, digest_algorithm::ctxsize, data, DBGC, DBGC_HDA, digest_final(), digest_init(), digest_update(), digest_algorithm::digestsize, EINVAL_KEY_EXCHANGE, ENOTSUP_SIG_HASH, EPERM_KEY_EXCHANGE, tls_server::exchange, tls_server::exchange_len, hash, tls_server::key, md5_sha1_algorithm, pubkey_algorithm::name, ntohs, tls_cipherspec_pair::pending, tls_cipher_suite::pubkey, pubkey_verify(), tls_client::random, tls_server::random, rc, tls_connection::server, sig, signature, tls_cipherspec::suite, tls_signature_hash_digest(), tls_signature_hash_pubkey(), tls_version(), TLS_VERSION_TLS_1_2, and tls_connection::tx.

Referenced by tls_send_client_key_exchange_dhe(), and tls_send_client_key_exchange_ecdhe().

◆ tls_send_client_key_exchange_dhe()

int tls_send_client_key_exchange_dhe ( struct tls_connection * tls)
static

Transmit Client Key Exchange record using DHE key exchange.

Parameters
tlsTLS connection
Return values
rcReturn status code

Definition at line 1591 of file tls.c.

1591 {
1592 uint8_t private[ sizeof ( tls->client.random.random ) ];
1593 const struct {
1594 uint16_t len;
1595 uint8_t data[0];
1596 } __attribute__ (( packed )) *dh_val[3];
1597 const void *data;
1598 size_t remaining;
1599 size_t frag_len;
1600 size_t param_len;
1601 unsigned int i;
1602 int rc;
1603
1604 /* Parse ServerKeyExchange */
1605 data = tls->server.exchange;
1606 remaining = tls->server.exchange_len;
1607 for ( i = 0 ; i < ( sizeof ( dh_val ) / sizeof ( dh_val[0] ) ) ; i++ ){
1608 dh_val[i] = data;
1609 if ( ( sizeof ( *dh_val[i] ) > remaining ) ||
1610 ( ntohs ( dh_val[i]->len ) > ( remaining -
1611 sizeof ( *dh_val[i] ) ) )){
1612 DBGC ( tls, "TLS %p received underlength "
1613 "ServerKeyExchange\n", tls );
1614 DBGC_HDA ( tls, 0, tls->server.exchange,
1615 tls->server.exchange_len );
1617 goto err_header;
1618 }
1619 frag_len = ( sizeof ( *dh_val[i] ) + ntohs ( dh_val[i]->len ));
1620 data += frag_len;
1621 remaining -= frag_len;
1622 }
1623 param_len = ( tls->server.exchange_len - remaining );
1624
1625 /* Verify parameter signature */
1626 if ( ( rc = tls_verify_dh_params ( tls, param_len ) ) != 0 )
1627 goto err_verify;
1628
1629 /* Generate Diffie-Hellman private key */
1630 if ( ( rc = tls_generate_random ( tls, private,
1631 sizeof ( private ) ) ) != 0 ) {
1632 goto err_random;
1633 }
1634
1635 /* Construct pre-master secret and ClientKeyExchange record */
1636 {
1637 typeof ( dh_val[0] ) dh_p = dh_val[0];
1638 typeof ( dh_val[1] ) dh_g = dh_val[1];
1639 typeof ( dh_val[2] ) dh_ys = dh_val[2];
1640 size_t len = ntohs ( dh_p->len );
1641 struct {
1642 uint32_t type_length;
1643 uint16_t dh_xs_len;
1644 uint8_t dh_xs[len];
1645 } __attribute__ (( packed )) *key_xchg;
1646 struct {
1647 uint8_t pre_master_secret[len];
1648 typeof ( *key_xchg ) key_xchg;
1649 } *dynamic;
1650 uint8_t *pre_master_secret;
1651
1652 /* Allocate space */
1653 dynamic = malloc ( sizeof ( *dynamic ) );
1654 if ( ! dynamic ) {
1655 rc = -ENOMEM;
1656 goto err_alloc;
1657 }
1658 pre_master_secret = dynamic->pre_master_secret;
1659 key_xchg = &dynamic->key_xchg;
1660 key_xchg->type_length =
1662 htonl ( sizeof ( *key_xchg ) -
1663 sizeof ( key_xchg->type_length ) ) );
1664 key_xchg->dh_xs_len = htons ( len );
1665
1666 /* Calculate pre-master secret and client public value */
1667 if ( ( rc = dhe_key ( dh_p->data, len,
1668 dh_g->data, ntohs ( dh_g->len ),
1669 dh_ys->data, ntohs ( dh_ys->len ),
1670 private, sizeof ( private ),
1671 key_xchg->dh_xs,
1672 pre_master_secret ) ) != 0 ) {
1673 DBGC ( tls, "TLS %p could not calculate DHE key: %s\n",
1674 tls, strerror ( rc ) );
1675 goto err_dhe_key;
1676 }
1677
1678 /* Strip leading zeroes from pre-master secret */
1679 while ( len && ( ! *pre_master_secret ) ) {
1680 pre_master_secret++;
1681 len--;
1682 }
1683
1684 /* Transmit Client Key Exchange record */
1685 if ( ( rc = tls_send_handshake ( tls, key_xchg,
1686 sizeof ( *key_xchg ) ) ) !=0){
1687 goto err_send_handshake;
1688 }
1689
1690 /* Generate master secret */
1691 tls_generate_master_secret ( tls, pre_master_secret, len );
1692
1693 err_send_handshake:
1694 err_dhe_key:
1695 free ( dynamic );
1696 }
1697 err_alloc:
1698 err_random:
1699 err_verify:
1700 err_header:
1701 return rc;
1702}
int dhe_key(const void *modulus, size_t len, const void *generator, size_t generator_len, const void *partner, size_t partner_len, const void *private, size_t private_len, void *public, void *shared)
Calculate Diffie-Hellman key.
Definition dhe.c:54
uint8_t random[32]
Random data.
Definition tls.h:316
static int tls_verify_dh_params(struct tls_connection *tls, size_t param_len)
Verify Diffie-Hellman parameter signature.
Definition tls.c:1502

References __attribute__, tls_connection::client, cpu_to_le32, data, DBGC, DBGC_HDA, dhe_key(), EINVAL_KEY_EXCHANGE, ENOMEM, tls_server::exchange, tls_server::exchange_len, free, htonl, htons, len, malloc(), ntohs, tls_client::random, tls_client_random::random, rc, tls_connection::server, strerror(), TLS_CLIENT_KEY_EXCHANGE, tls_generate_master_secret(), tls_generate_random(), tls_send_handshake(), tls_verify_dh_params(), and typeof().

◆ tls_send_client_key_exchange_ecdhe()

int tls_send_client_key_exchange_ecdhe ( struct tls_connection * tls)
static

Transmit Client Key Exchange record using ECDHE key exchange.

Parameters
tlsTLS connection
Return values
rcReturn status code

Definition at line 1716 of file tls.c.

1716 {
1717 struct tls_named_curve *curve;
1718 const struct {
1719 uint8_t curve_type;
1720 uint16_t named_curve;
1721 uint8_t public_len;
1722 uint8_t public[0];
1723 } __attribute__ (( packed )) *ecdh;
1724 size_t param_len;
1725 size_t pointsize;
1726 size_t keysize;
1727 size_t offset;
1728 int rc;
1729
1730 /* Parse ServerKeyExchange record */
1731 ecdh = tls->server.exchange;
1732 if ( ( sizeof ( *ecdh ) > tls->server.exchange_len ) ||
1733 ( ecdh->public_len > ( tls->server.exchange_len -
1734 sizeof ( *ecdh ) ) ) ) {
1735 DBGC ( tls, "TLS %p received underlength ServerKeyExchange\n",
1736 tls );
1737 DBGC_HDA ( tls, 0, tls->server.exchange,
1738 tls->server.exchange_len );
1739 return -EINVAL_KEY_EXCHANGE;
1740 }
1741 param_len = ( sizeof ( *ecdh ) + ecdh->public_len );
1742
1743 /* Verify parameter signature */
1744 if ( ( rc = tls_verify_dh_params ( tls, param_len ) ) != 0 )
1745 return rc;
1746
1747 /* Identify named curve */
1748 if ( ecdh->curve_type != TLS_NAMED_CURVE_TYPE ) {
1749 DBGC ( tls, "TLS %p unsupported curve type %d\n",
1750 tls, ecdh->curve_type );
1751 DBGC_HDA ( tls, 0, tls->server.exchange,
1752 tls->server.exchange_len );
1753 return -ENOTSUP_CURVE;
1754 }
1755 curve = tls_find_named_curve ( ecdh->named_curve );
1756 if ( ! curve ) {
1757 DBGC ( tls, "TLS %p unsupported named curve %d\n",
1758 tls, ntohs ( ecdh->named_curve ) );
1759 DBGC_HDA ( tls, 0, tls->server.exchange,
1760 tls->server.exchange_len );
1761 return -ENOTSUP_CURVE;
1762 }
1763 DBGC ( tls, "TLS %p using named curve %s\n", tls, curve->curve->name );
1764 pointsize = curve->curve->pointsize;
1765 keysize = curve->curve->keysize;
1766 offset = ( curve->format ? 1 : 0 );
1767
1768 /* Check key length */
1769 if ( ecdh->public_len != ( offset + pointsize ) ) {
1770 DBGC ( tls, "TLS %p invalid %s key\n",
1771 tls, curve->curve->name );
1772 DBGC_HDA ( tls, 0, tls->server.exchange,
1773 tls->server.exchange_len );
1774 return -EINVAL_KEY_EXCHANGE;
1775 }
1776
1777 /* Check curve point format byte (if present) */
1778 if ( curve->format && ( ecdh->public[0] != curve->format ) ) {
1779 DBGC ( tls, "TLS %p invalid %s curve point format\n",
1780 tls, curve->curve->name );
1781 DBGC_HDA ( tls, 0, tls->server.exchange,
1782 tls->server.exchange_len );
1783 return -EINVAL_KEY_EXCHANGE;
1784 }
1785
1786 /* Construct pre-master secret and ClientKeyExchange record */
1787 {
1788 uint8_t private[keysize];
1789 uint8_t pre_master_secret[pointsize];
1790 struct {
1791 uint32_t type_length;
1792 uint8_t public_len;
1793 uint8_t public[ecdh->public_len];
1794 } __attribute__ (( packed )) key_xchg;
1795
1796 /* Generate ephemeral private key */
1797 if ( ( rc = tls_generate_random ( tls, private,
1798 sizeof ( private ) ) ) != 0){
1799 return rc;
1800 }
1801
1802 /* Exchange keys */
1803 if ( ( rc = ecdhe_key ( curve->curve, ( ecdh->public + offset ),
1804 private, ( key_xchg.public + offset ),
1805 pre_master_secret ) ) != 0 ) {
1806 DBGC ( tls, "TLS %p could not exchange ECDHE key: %s\n",
1807 tls, strerror ( rc ) );
1808 return rc;
1809 }
1810
1811 /* Generate Client Key Exchange record */
1812 key_xchg.type_length =
1814 htonl ( sizeof ( key_xchg ) -
1815 sizeof ( key_xchg.type_length ) ) );
1816 key_xchg.public_len = sizeof ( key_xchg.public );
1817 if ( curve->format )
1818 key_xchg.public[0] = curve->format;
1819
1820 /* Transmit Client Key Exchange record */
1821 if ( ( rc = tls_send_handshake ( tls, &key_xchg,
1822 sizeof ( key_xchg ) ) ) !=0){
1823 return rc;
1824 }
1825
1826 /* Generate master secret */
1827 tls_generate_master_secret ( tls, pre_master_secret,
1828 curve->pre_master_secret_len );
1829 }
1830
1831 return 0;
1832}
uint16_t offset
Offset to command line.
Definition bzimage.h:3
int ecdhe_key(struct elliptic_curve *curve, const void *partner, const void *private, void *public, void *shared)
Calculate ECDHE key.
Definition ecdhe.c:47
const char * name
Curve name.
Definition crypto.h:180
size_t keysize
Scalar (and private key) size.
Definition crypto.h:184
size_t pointsize
Point (and public key) size.
Definition crypto.h:182
uint8_t pre_master_secret_len
Pre-master secret length.
Definition tls.h:249
uint8_t format
Curve point format byte (if any)
Definition tls.h:247
#define ENOTSUP_CURVE
Definition tls.c:162
static struct tls_named_curve * tls_find_named_curve(unsigned int named_curve)
Identify named curve.
Definition tls.c:1090
#define TLS_NAMED_CURVE_TYPE
TLS named curved type.
Definition tls.h:235
u16 keysize
Length of encryption key to be used, network byte order.
Definition wpa.h:10

References __attribute__, cpu_to_le32, tls_named_curve::curve, DBGC, DBGC_HDA, ecdhe_key(), EINVAL_KEY_EXCHANGE, ENOTSUP_CURVE, tls_server::exchange, tls_server::exchange_len, tls_named_curve::format, htonl, elliptic_curve::keysize, keysize, elliptic_curve::name, ntohs, offset, elliptic_curve::pointsize, tls_named_curve::pre_master_secret_len, rc, tls_connection::server, strerror(), TLS_CLIENT_KEY_EXCHANGE, tls_find_named_curve(), tls_generate_master_secret(), tls_generate_random(), TLS_NAMED_CURVE_TYPE, tls_send_handshake(), and tls_verify_dh_params().

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

1846 {
1847 struct tls_cipherspec *cipherspec = &tls->tx.cipherspec.pending;
1848 struct tls_cipher_suite *suite = cipherspec->suite;
1849 int rc;
1850
1851 /* Transmit Client Key Exchange record via key exchange algorithm */
1852 if ( ( rc = suite->exchange->exchange ( tls ) ) != 0 ) {
1853 DBGC ( tls, "TLS %p could not exchange keys: %s\n",
1854 tls, strerror ( rc ) );
1855 return rc;
1856 }
1857
1858 /* Generate keys from master secret */
1859 if ( ( rc = tls_generate_keys ( tls ) ) != 0 ) {
1860 DBGC ( tls, "TLS %p could not generate keys: %s\n",
1861 tls, strerror ( rc ) );
1862 return rc;
1863 }
1864
1865 return 0;
1866}
int(* exchange)(struct tls_connection *tls)
Transmit Client Key Exchange record.
Definition tls.h:199
static int tls_generate_keys(struct tls_connection *tls)
Generate key material.
Definition tls.c:697

References tls_tx::cipherspec, DBGC, tls_cipher_suite::exchange, tls_key_exchange_algorithm::exchange, tls_cipherspec_pair::pending, rc, strerror(), tls_cipherspec::suite, tls_generate_keys(), 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 1874 of file tls.c.

1874 {
1875 struct digest_algorithm *digest = tls->handshake_digest;
1876 struct x509_certificate *cert = x509_first ( tls->client.chain );
1877 struct pubkey_algorithm *pubkey = cert->signature_algorithm->pubkey;
1878 struct asn1_cursor *key = privkey_cursor ( tls->client.key );
1879 uint8_t digest_out[ digest->digestsize ];
1880 struct tls_signature_hash_algorithm *sig_hash = NULL;
1881 struct asn1_builder builder = { NULL, 0 };
1882 int rc;
1883
1884 /* Generate digest to be signed */
1885 tls_verify_handshake ( tls, digest_out );
1886
1887 /* TLSv1.2 and later use explicit algorithm identifiers */
1888 if ( tls_version ( tls, TLS_VERSION_TLS_1_2 ) ) {
1889 sig_hash = tls_signature_hash_algorithm ( pubkey, digest );
1890 if ( ! sig_hash ) {
1891 DBGC ( tls, "TLS %p could not identify (%s,%s) "
1892 "signature and hash algorithm\n", tls,
1893 pubkey->name, digest->name );
1895 goto err_sig_hash;
1896 }
1897 }
1898
1899 /* Sign digest */
1900 if ( ( rc = pubkey_sign ( pubkey, key, digest, digest_out,
1901 &builder ) ) != 0 ) {
1902 DBGC ( tls, "TLS %p could not sign %s digest using %s client "
1903 "private key: %s\n", tls, digest->name, pubkey->name,
1904 strerror ( rc ) );
1905 goto err_pubkey_sign;
1906 }
1907
1908 /* Construct Certificate Verify record */
1909 {
1910 int use_sig_hash = ( ( sig_hash == NULL ) ? 0 : 1 );
1911 struct {
1912 uint32_t type_length;
1913 struct tls_signature_hash_id sig_hash[use_sig_hash];
1914 uint16_t signature_len;
1915 } __attribute__ (( packed )) header;
1916
1917 header.type_length = ( cpu_to_le32 ( TLS_CERTIFICATE_VERIFY ) |
1918 htonl ( builder.len +
1919 sizeof ( header ) -
1920 sizeof ( header.type_length )));
1921 if ( use_sig_hash ) {
1922 memcpy ( &header.sig_hash[0], &sig_hash->code,
1923 sizeof ( header.sig_hash[0] ) );
1924 }
1925 header.signature_len = htons ( builder.len );
1926
1927 if ( ( rc = asn1_prepend_raw ( &builder, &header,
1928 sizeof ( header ) ) ) != 0 ) {
1929 DBGC ( tls, "TLS %p could not construct Certificate "
1930 "Verify: %s\n", tls, strerror ( rc ) );
1931 goto err_prepend;
1932 }
1933 }
1934
1935 /* Transmit record */
1936 if ( ( rc = tls_send_handshake ( tls, builder.data,
1937 builder.len ) ) != 0 ) {
1938 goto err_send;
1939 }
1940
1941 err_send:
1942 err_prepend:
1943 err_pubkey_sign:
1944 err_sig_hash:
1945 free ( builder.data );
1946 return rc;
1947}
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:301
static struct asn1_cursor * privkey_cursor(struct private_key *key)
Get private key ASN.1 cursor.
Definition privkey.h:53
struct pubkey_algorithm * pubkey
Public-key algorithm (if applicable)
Definition asn1.h:414
struct asn1_algorithm * signature_algorithm
Signature algorithm.
Definition x509.h:239
static struct tls_signature_hash_algorithm * tls_signature_hash_algorithm(struct pubkey_algorithm *pubkey, struct digest_algorithm *digest)
Find TLS signature and hash algorithm.
Definition tls.c:1020
#define TLS_CERTIFICATE_VERIFY
Definition tls.h:77
static struct x509_certificate * x509_first(struct x509_chain *chain)
Get first certificate in X.509 certificate chain.
Definition x509.h:311

References __attribute__, asn1_prepend_raw(), tls_client::chain, tls_connection::client, tls_signature_hash_algorithm::code, cpu_to_le32, asn1_builder::data, DBGC, digest_algorithm::digestsize, ENOTSUP_SIG_HASH, free, tls_connection::handshake_digest, header, htonl, htons, key, tls_client::key, asn1_builder::len, memcpy(), digest_algorithm::name, pubkey_algorithm::name, NULL, privkey_cursor(), asn1_algorithm::pubkey, pubkey_sign(), rc, x509_certificate::signature_algorithm, strerror(), TLS_CERTIFICATE_VERIFY, tls_send_handshake(), tls_signature_hash_algorithm(), tls_verify_handshake(), tls_version(), TLS_VERSION_TLS_1_2, and x509_first().

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

1955 {
1956 static const struct {
1957 uint8_t spec;
1958 } __attribute__ (( packed )) change_cipher = {
1959 .spec = TLS_CHANGE_CIPHER_SPEC,
1960 };
1961
1963 &change_cipher, sizeof ( change_cipher ) );
1964}
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 1972 of file tls.c.

1972 {
1973 struct digest_algorithm *digest = tls->handshake_digest;
1974 struct {
1975 uint32_t type_length;
1976 uint8_t verify_data[ sizeof ( tls->verify.client ) ];
1977 } __attribute__ (( packed )) finished;
1978 uint8_t digest_out[ digest->digestsize ];
1979 int rc;
1980
1981 /* Construct client verification data */
1982 tls_verify_handshake ( tls, digest_out );
1983 tls_prf_label ( tls, &tls->master_secret, sizeof ( tls->master_secret ),
1984 tls->verify.client, sizeof ( tls->verify.client ),
1985 "client finished", digest_out, sizeof ( digest_out ) );
1986
1987 /* Construct record */
1988 memset ( &finished, 0, sizeof ( finished ) );
1989 finished.type_length = ( cpu_to_le32 ( TLS_FINISHED ) |
1990 htonl ( sizeof ( finished ) -
1991 sizeof ( finished.type_length ) ) );
1992 memcpy ( finished.verify_data, tls->verify.client,
1993 sizeof ( finished.verify_data ) );
1994
1995 /* Transmit record */
1996 if ( ( rc = tls_send_handshake ( tls, &finished,
1997 sizeof ( finished ) ) ) != 0 )
1998 return rc;
1999
2000 /* Mark client as finished */
2001 pending_put ( &tls->client.negotiation );
2002
2003 return 0;
2004}
#define TLS_FINISHED
Definition tls.h:79

References __attribute__, tls_connection::client, tls_verify_data::client, cpu_to_le32, digest_algorithm::digestsize, tls_connection::handshake_digest, htonl, tls_connection::master_secret, memcpy(), memset(), tls_client::negotiation, pending_put(), rc, TLS_FINISHED, tls_prf_label, tls_send_handshake(), tls_verify_handshake(), 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 2036 of file tls.c.

2037 {
2038 const struct {
2039 uint8_t spec;
2040 } __attribute__ (( packed )) *change_cipher = iobuf->data;
2041 size_t len = iob_len ( iobuf );
2042 int rc;
2043
2044 /* Sanity check */
2045 if ( ( sizeof ( *change_cipher ) != len ) ||
2046 ( change_cipher->spec != TLS_CHANGE_CIPHER_SPEC ) ) {
2047 DBGC ( tls, "TLS %p received invalid Change Cipher\n", tls );
2048 DBGC_HD ( tls, change_cipher, len );
2049 return -EINVAL_CHANGE_CIPHER;
2050 }
2051 iob_pull ( iobuf, sizeof ( *change_cipher ) );
2052
2053 /* Change receive cipher spec */
2054 if ( ( rc = tls_change_cipher ( tls, &tls->rx.cipherspec ) ) != 0 ) {
2055 DBGC ( tls, "TLS %p could not activate RX cipher: %s\n",
2056 tls, strerror ( rc ) );
2057 return rc;
2058 }
2059 tls->rx.seq = ~( ( uint64_t ) 0 );
2060
2061 return 0;
2062}
unsigned long long uint64_t
Definition stdint.h:13
#define iob_pull(iobuf, len)
Definition iobuf.h:107
uint64_t seq
Sequence number.
Definition tls.h:389
#define EINVAL_CHANGE_CIPHER
Definition tls.c:58
static int tls_change_cipher(struct tls_connection *tls, struct tls_cipherspec_pair *pair)
Activate next cipher suite.
Definition tls.c:987

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

Referenced by tls_new_record().

◆ tls_new_alert()

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

Receive new Alert record.

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

Definition at line 2071 of file tls.c.

2072 {
2073 const struct {
2074 uint8_t level;
2075 uint8_t description;
2076 char next[0];
2077 } __attribute__ (( packed )) *alert = iobuf->data;
2078 size_t len = iob_len ( iobuf );
2079
2080 /* Sanity check */
2081 if ( sizeof ( *alert ) != len ) {
2082 DBGC ( tls, "TLS %p received overlength Alert\n", tls );
2083 DBGC_HD ( tls, alert, len );
2084 return -EINVAL_ALERT;
2085 }
2086 iob_pull ( iobuf, sizeof ( *alert ) );
2087
2088 /* Handle alert */
2089 switch ( alert->level ) {
2090 case TLS_ALERT_WARNING:
2091 switch ( alert->description ) {
2093 DBGC ( tls, "TLS %p closed by notification\n", tls );
2094 tls_close ( tls, 0 );
2095 break;
2096 default:
2097 DBGC ( tls, "TLS %p received warning alert %d\n",
2098 tls, alert->description );
2099 break;
2100 }
2101 return 0;
2102 case TLS_ALERT_FATAL:
2103 DBGC ( tls, "TLS %p received fatal alert %d\n",
2104 tls, alert->description );
2105 return -EPERM_ALERT;
2106 default:
2107 DBGC ( tls, "TLS %p received unknown alert level %d"
2108 "(alert %d)\n", tls, alert->level, alert->description );
2109 return -EIO_ALERT;
2110 }
2111}
uint32_t next
Next descriptor address.
Definition dwmac.h:11
#define EINVAL_ALERT
Definition tls.c:62
#define EPERM_ALERT
Definition tls.c:166
#define EIO_ALERT
Definition tls.c:114
static void tls_close(struct tls_connection *tls, int rc)
Finish with TLS connection.
Definition tls.c:423
#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 2121 of file tls.c.

2123 {
2124
2125 /* Ignore if a handshake is in progress */
2126 if ( ! tls_ready ( tls ) ) {
2127 DBGC ( tls, "TLS %p ignoring Hello Request\n", tls );
2128 return 0;
2129 }
2130
2131 /* Fail unless server supports secure renegotiation */
2132 if ( ! ( tls->secure_renegotiation && tls->extended_master_secret ) ) {
2133 DBGC ( tls, "TLS %p refusing to renegotiate insecurely\n",
2134 tls );
2135 return -EPERM_RENEG_INSECURE;
2136 }
2137
2138 /* Restart negotiation */
2139 tls_restart ( tls );
2140
2141 return 0;
2142}
static int tls_ready(struct tls_connection *tls)
Determine if TLS connection is ready for application data.
Definition tls.c:261
static void tls_restart(struct tls_connection *tls)
Restart negotiation.
Definition tls.c:1135
#define EPERM_RENEG_INSECURE
Definition tls.c:174

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

2153 {
2154 const struct {
2156 uint8_t random[32];
2157 uint8_t session_id_len;
2158 uint8_t session_id[0];
2159 } __attribute__ (( packed )) *hello_a = data;
2160 const uint8_t *session_id;
2161 const struct {
2162 uint16_t cipher_suite;
2163 uint8_t compression_method;
2164 char next[0];
2165 } __attribute__ (( packed )) *hello_b;
2166 const struct {
2167 uint16_t len;
2168 uint8_t data[0];
2169 } __attribute__ (( packed )) *exts;
2170 const struct {
2171 uint16_t type;
2172 uint16_t len;
2173 uint8_t data[0];
2174 } __attribute__ (( packed )) *ext;
2175 const struct {
2176 uint8_t len;
2177 uint8_t data[0];
2178 } __attribute__ (( packed )) *reneg = NULL;
2179 const struct {
2180 uint8_t data[0];
2181 } __attribute__ (( packed )) *ems = NULL;
2183 size_t exts_len;
2184 size_t ext_len;
2185 size_t remaining;
2186 int rc;
2187
2188 /* Parse header */
2189 if ( ( sizeof ( *hello_a ) > len ) ||
2190 ( hello_a->session_id_len > ( len - sizeof ( *hello_a ) ) ) ||
2191 ( sizeof ( *hello_b ) > ( len - sizeof ( *hello_a ) -
2192 hello_a->session_id_len ) ) ) {
2193 DBGC ( tls, "TLS %p received underlength Server Hello\n", tls );
2194 DBGC_HD ( tls, data, len );
2195 return -EINVAL_HELLO;
2196 }
2197 session_id = hello_a->session_id;
2198 hello_b = ( ( void * ) ( session_id + hello_a->session_id_len ) );
2199
2200 /* Parse extensions, if present */
2201 remaining = ( len - sizeof ( *hello_a ) - hello_a->session_id_len -
2202 sizeof ( *hello_b ) );
2203 if ( remaining ) {
2204
2205 /* Parse extensions length */
2206 exts = ( ( void * ) hello_b->next );
2207 if ( ( sizeof ( *exts ) > remaining ) ||
2208 ( ( exts_len = ntohs ( exts->len ) ) >
2209 ( remaining - sizeof ( *exts ) ) ) ) {
2210 DBGC ( tls, "TLS %p received underlength extensions\n",
2211 tls );
2212 DBGC_HD ( tls, data, len );
2213 return -EINVAL_HELLO;
2214 }
2215
2216 /* Parse extensions */
2217 for ( ext = ( ( void * ) exts->data ), remaining = exts_len ;
2218 remaining ;
2219 ext = ( ( ( void * ) ext ) + sizeof ( *ext ) + ext_len ),
2220 remaining -= ( sizeof ( *ext ) + ext_len ) ) {
2221
2222 /* Parse extension length */
2223 if ( ( sizeof ( *ext ) > remaining ) ||
2224 ( ( ext_len = ntohs ( ext->len ) ) >
2225 ( remaining - sizeof ( *ext ) ) ) ) {
2226 DBGC ( tls, "TLS %p received underlength "
2227 "extension\n", tls );
2228 DBGC_HD ( tls, data, len );
2229 return -EINVAL_HELLO;
2230 }
2231
2232 /* Record known extensions */
2233 switch ( ext->type ) {
2234 case htons ( TLS_RENEGOTIATION_INFO ) :
2235 reneg = ( ( void * ) ext->data );
2236 if ( ( sizeof ( *reneg ) > ext_len ) ||
2237 ( reneg->len >
2238 ( ext_len - sizeof ( *reneg ) ) ) ) {
2239 DBGC ( tls, "TLS %p received "
2240 "underlength renegotiation "
2241 "info\n", tls );
2242 DBGC_HD ( tls, data, len );
2243 return -EINVAL_HELLO;
2244 }
2245 break;
2247 ems = ( ( void * ) ext->data );
2248 break;
2249 }
2250 }
2251 }
2252
2253 /* Check and store protocol version */
2254 version = ntohs ( hello_a->version );
2255 if ( version < TLS_VERSION_MIN ) {
2256 DBGC ( tls, "TLS %p does not support protocol version %d.%d\n",
2257 tls, ( version >> 8 ), ( version & 0xff ) );
2258 return -ENOTSUP_VERSION;
2259 }
2260 if ( version > tls->version ) {
2261 DBGC ( tls, "TLS %p server attempted to illegally upgrade to "
2262 "protocol version %d.%d\n",
2263 tls, ( version >> 8 ), ( version & 0xff ) );
2264 return -EPROTO_VERSION;
2265 }
2266 tls->version = version;
2267 DBGC ( tls, "TLS %p using protocol version %d.%d\n",
2268 tls, ( version >> 8 ), ( version & 0xff ) );
2269
2270 /* Select cipher suite */
2271 if ( ( rc = tls_select_cipher ( tls, hello_b->cipher_suite ) ) != 0 )
2272 return rc;
2273
2274 /* Add preceding Client Hello to handshake digest */
2275 if ( ( rc = tls_client_hello ( tls, tls_add_handshake ) ) != 0 )
2276 return rc;
2277
2278 /* Copy out server random bytes */
2279 memcpy ( &tls->server.random, &hello_a->random,
2280 sizeof ( tls->server.random ) );
2281
2282 /* Handle extended master secret */
2283 tls->extended_master_secret = ( !! ems );
2284
2285 /* Check session ID */
2286 if ( hello_a->session_id_len &&
2287 ( hello_a->session_id_len == tls->session_id_len ) &&
2288 ( memcmp ( session_id, tls->session_id,
2289 tls->session_id_len ) == 0 ) ) {
2290
2291 /* Session ID match: reuse master secret */
2292 DBGC ( tls, "TLS %p resuming session ID:\n", tls );
2293 DBGC_HDA ( tls, 0, tls->session_id, tls->session_id_len );
2294 if ( ( rc = tls_generate_keys ( tls ) ) != 0 )
2295 return rc;
2296
2297 /* Ensure master secret generation method matches */
2298 if ( tls->extended_master_secret !=
2300 DBGC ( tls, "TLS %p mismatched extended master secret "
2301 "extension\n", tls );
2302 return -EPERM_EMS;
2303 }
2304
2305 } else {
2306
2307 /* Record new session ID, if present */
2308 if ( hello_a->session_id_len &&
2309 ( hello_a->session_id_len <= sizeof ( tls->session_id ))){
2310 tls->session_id_len = hello_a->session_id_len;
2311 memcpy ( tls->session_id, session_id,
2312 tls->session_id_len );
2313 DBGC ( tls, "TLS %p new session ID:\n", tls );
2314 DBGC_HDA ( tls, 0, tls->session_id,
2315 tls->session_id_len );
2316 }
2317 }
2318
2319 /* Handle secure renegotiation */
2320 if ( tls->secure_renegotiation ) {
2321
2322 /* Secure renegotiation is expected; verify data */
2323 if ( ( reneg == NULL ) ||
2324 ( reneg->len != sizeof ( tls->verify ) ) ||
2325 ( memcmp ( reneg->data, &tls->verify,
2326 sizeof ( tls->verify ) ) != 0 ) ) {
2327 DBGC ( tls, "TLS %p server failed secure "
2328 "renegotiation\n", tls );
2329 return -EPERM_RENEG_VERIFY;
2330 }
2331
2332 } else if ( reneg != NULL ) {
2333
2334 /* Secure renegotiation is being enabled */
2335 if ( reneg->len != 0 ) {
2336 DBGC ( tls, "TLS %p server provided non-empty initial "
2337 "renegotiation\n", tls );
2338 return -EPERM_RENEG_VERIFY;
2339 }
2340 tls->secure_renegotiation = 1;
2341 }
2342
2343 return 0;
2344}
uint16_t ext
Extended status.
Definition ena.h:9
#define ENOTSUP_VERSION
Definition stp.c:46
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition string.c:115
int extended_master_secret
Extended master secret flag.
Definition tls.h:366
#define EPERM_EMS
Definition tls.c:186
#define EINVAL_HELLO
Definition tls.c:66
static int tls_select_cipher(struct tls_connection *tls, unsigned int cipher_suite)
Select next cipher suite.
Definition tls.c:944
#define EPROTO_VERSION
Definition tls.c:190
#define EPERM_RENEG_VERIFY
Definition tls.c:178

References __attribute__, data, DBGC, DBGC_HD, DBGC_HDA, EINVAL_HELLO, ENOTSUP_VERSION, EPERM_EMS, EPERM_RENEG_VERIFY, EPROTO_VERSION, ext, tls_connection::extended_master_secret, tls_session::extended_master_secret, htons, len, memcmp(), memcpy(), next, ntohs, NULL, random(), tls_server::random, rc, tls_connection::secure_renegotiation, tls_connection::server, tls_connection::session, tls_connection::session_id, tls_connection::session_id_len, tls_add_handshake(), tls_client_hello(), TLS_EXTENDED_MASTER_SECRET, tls_generate_keys(), TLS_RENEGOTIATION_INFO, tls_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 2354 of file tls.c.

2355 {
2356 const struct {
2358 uint16_t len;
2359 uint8_t ticket[0];
2360 } __attribute__ (( packed )) *new_session_ticket = data;
2361 size_t ticket_len;
2362
2363 /* Parse header */
2364 if ( sizeof ( *new_session_ticket ) > len ) {
2365 DBGC ( tls, "TLS %p received underlength New Session Ticket\n",
2366 tls );
2367 DBGC_HD ( tls, data, len );
2368 return -EINVAL_TICKET;
2369 }
2370 ticket_len = ntohs ( new_session_ticket->len );
2371 if ( ticket_len > ( len - sizeof ( *new_session_ticket ) ) ) {
2372 DBGC ( tls, "TLS %p received overlength New Session Ticket\n",
2373 tls );
2374 DBGC_HD ( tls, data, len );
2375 return -EINVAL_TICKET;
2376 }
2377
2378 /* Free any unapplied new session ticket */
2379 free ( tls->new_session_ticket );
2380 tls->new_session_ticket = NULL;
2381 tls->new_session_ticket_len = 0;
2382
2383 /* Record ticket */
2384 tls->new_session_ticket = malloc ( ticket_len );
2385 if ( ! tls->new_session_ticket )
2386 return -ENOMEM;
2387 memcpy ( tls->new_session_ticket, new_session_ticket->ticket,
2388 ticket_len );
2389 tls->new_session_ticket_len = ticket_len;
2390 DBGC ( tls, "TLS %p new session ticket:\n", tls );
2391 DBGC_HDA ( tls, 0, tls->new_session_ticket,
2393
2394 return 0;
2395}
size_t new_session_ticket_len
Length of new session ticket.
Definition tls.h:452
#define EINVAL_TICKET
Definition tls.c:106
u32 lifetime
For Lifetime-type KDEs, the lifetime in seconds.
Definition wpa.h:27

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

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

2406 {
2407 size_t remaining = len;
2408 int rc;
2409
2410 /* Free any existing certificate chain */
2411 memset ( &tls->server.key, 0, sizeof ( tls->server.key ) );
2412 x509_chain_put ( tls->server.chain );
2413 tls->server.chain = NULL;
2414
2415 /* Create certificate chain */
2416 tls->server.chain = x509_alloc_chain();
2417 if ( ! tls->server.chain ) {
2418 rc = -ENOMEM_CHAIN;
2419 goto err_alloc_chain;
2420 }
2421
2422 /* Add certificates to chain */
2423 while ( remaining ) {
2424 const struct {
2426 uint8_t data[0];
2427 } __attribute__ (( packed )) *certificate = data;
2428 size_t certificate_len;
2429 size_t record_len;
2430 struct x509_certificate *cert;
2431
2432 /* Parse header */
2433 if ( sizeof ( *certificate ) > remaining ) {
2434 DBGC ( tls, "TLS %p underlength certificate:\n", tls );
2435 DBGC_HDA ( tls, 0, data, remaining );
2437 goto err_underlength;
2438 }
2439 certificate_len = tls_uint24 ( &certificate->length );
2440 if ( certificate_len > ( remaining - sizeof ( *certificate ) )){
2441 DBGC ( tls, "TLS %p overlength certificate:\n", tls );
2442 DBGC_HDA ( tls, 0, data, remaining );
2444 goto err_overlength;
2445 }
2446 record_len = ( sizeof ( *certificate ) + certificate_len );
2447
2448 /* Add certificate to chain */
2449 if ( ( rc = x509_append_raw ( tls->server.chain,
2450 certificate->data,
2451 certificate_len ) ) != 0 ) {
2452 DBGC ( tls, "TLS %p could not append certificate: %s\n",
2453 tls, strerror ( rc ) );
2454 DBGC_HDA ( tls, 0, data, remaining );
2455 goto err_parse;
2456 }
2457 cert = x509_last ( tls->server.chain );
2458 DBGC ( tls, "TLS %p found certificate %s\n",
2459 tls, x509_name ( cert ) );
2460
2461 /* Move to next certificate in list */
2462 data += record_len;
2463 remaining -= record_len;
2464 }
2465
2466 return 0;
2467
2468 err_parse:
2469 err_overlength:
2470 err_underlength:
2471 memset ( &tls->server.key, 0, sizeof ( tls->server.key ) );
2472 x509_chain_put ( tls->server.chain );
2473 tls->server.chain = NULL;
2474 err_alloc_chain:
2475 return rc;
2476}
#define ENOMEM_CHAIN
Definition tls.c:126
#define EINVAL_CERTIFICATE
Definition tls.c:70
static unsigned long tls_uint24(const tls24_t *field24)
Extract 24-bit field value.
Definition tls.c:238
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, tls_server::key, len, length, memset(), 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 2486 of file tls.c.

2487 {
2488 const struct {
2490 uint8_t certificates[0];
2491 } __attribute__ (( packed )) *certificate = data;
2492 size_t certificates_len;
2493 int rc;
2494
2495 /* Parse header */
2496 if ( sizeof ( *certificate ) > len ) {
2497 DBGC ( tls, "TLS %p received underlength Server Certificate\n",
2498 tls );
2499 DBGC_HD ( tls, data, len );
2500 return -EINVAL_CERTIFICATES;
2501 }
2502 certificates_len = tls_uint24 ( &certificate->length );
2503 if ( certificates_len > ( len - sizeof ( *certificate ) ) ) {
2504 DBGC ( tls, "TLS %p received overlength Server Certificate\n",
2505 tls );
2506 DBGC_HD ( tls, data, len );
2507 return -EINVAL_CERTIFICATES;
2508 }
2509
2510 /* Parse certificate chain */
2511 if ( ( rc = tls_parse_chain ( tls, certificate->certificates,
2512 certificates_len ) ) != 0 )
2513 return rc;
2514
2515 return 0;
2516}
#define EINVAL_CERTIFICATES
Definition tls.c:74
static int tls_parse_chain(struct tls_connection *tls, const void *data, size_t len)
Parse certificate chain.
Definition tls.c:2405

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

2527 {
2528
2529 /* Free any existing server key exchange record */
2530 free ( tls->server.exchange );
2531 tls->server.exchange_len = 0;
2532
2533 /* Allocate copy of server key exchange record */
2534 tls->server.exchange = malloc ( len );
2535 if ( ! tls->server.exchange )
2536 return -ENOMEM;
2537
2538 /* Store copy of server key exchange record for later
2539 * processing. We cannot verify the signature at this point
2540 * since the certificate validation will not yet have
2541 * completed.
2542 */
2543 memcpy ( tls->server.exchange, data, len );
2544 tls->server.exchange_len = len;
2545
2546 return 0;
2547}

References data, ENOMEM, tls_server::exchange, tls_server::exchange_len, free, len, malloc(), memcpy(), and tls_connection::server.

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

2559 {
2560 struct x509_certificate *cert;
2561 int rc;
2562
2563 /* We can only send a single certificate, so there is no point
2564 * in parsing the Certificate Request.
2565 */
2566
2567 /* Free any existing client certificate chain */
2568 x509_chain_put ( tls->client.chain );
2569 tls->client.chain = NULL;
2570
2571 /* Create client certificate chain */
2572 tls->client.chain = x509_alloc_chain();
2573 if ( ! tls->client.chain ) {
2574 rc = -ENOMEM;
2575 goto err_alloc;
2576 }
2577
2578 /* Determine client certificate to be sent, if any */
2579 cert = x509_find_key ( NULL, tls->client.key );
2580 if ( cert ) {
2581 DBGC ( tls, "TLS %p selected client certificate %s\n",
2582 tls, x509_name ( cert ) );
2583
2584 /* Append client certificate to chain */
2585 if ( ( rc = x509_append ( tls->client.chain, cert ) ) != 0 )
2586 goto err_append;
2587
2588 /* Append any relevant issuer certificates */
2589 if ( ( rc = x509_auto_append ( tls->client.chain,
2590 &certstore ) ) != 0 )
2591 goto err_auto_append;
2592 } else {
2593
2594 /* Send an empty certificate chain */
2595 DBGC ( tls, "TLS %p could not find certificate corresponding "
2596 "to private key\n", tls );
2597 }
2598
2599 return 0;
2600
2601 err_auto_append:
2602 err_append:
2603 x509_chain_put ( tls->client.chain );
2604 tls->client.chain = NULL;
2605 err_alloc:
2606 return rc;
2607}
struct x509_chain certstore
Certificate store.
Definition certstore.c:90
int x509_auto_append(struct x509_chain *chain, struct x509_chain *store)
Append X.509 certificates to X.509 certificate chain.
Definition x509.c:1868
struct x509_certificate * x509_find_key(struct x509_chain *store, struct private_key *key)
Identify X.509 certificate by corresponding public key.
Definition x509.c:1835
int x509_append(struct x509_chain *chain, struct x509_certificate *cert)
Append X.509 certificate to X.509 certificate chain.
Definition x509.c:1638

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

Referenced by tls_new_handshake().

◆ tls_new_server_hello_done()

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

Receive new Server Hello Done handshake record.

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

Definition at line 2617 of file tls.c.

2618 {
2619 const struct {
2620 char next[0];
2621 } __attribute__ (( packed )) *hello_done = data;
2622 int rc;
2623
2624 /* Sanity check */
2625 if ( sizeof ( *hello_done ) != len ) {
2626 DBGC ( tls, "TLS %p received overlength Server Hello Done\n",
2627 tls );
2628 DBGC_HD ( tls, data, len );
2629 return -EINVAL_HELLO_DONE;
2630 }
2631
2632 /* Begin certificate validation */
2633 if ( ( rc = create_validator ( &tls->server.validator,
2634 tls->server.chain,
2635 tls->server.root ) ) != 0 ) {
2636 DBGC ( tls, "TLS %p could not start certificate validation: "
2637 "%s\n", tls, strerror ( rc ) );
2638 return rc;
2639 }
2640 pending_get ( &tls->server.validation );
2641
2642 return 0;
2643}
#define EINVAL_HELLO_DONE
Definition tls.c:78
int create_validator(struct interface *job, struct x509_chain *chain, struct x509_root *root)
Instantiate a certificate validator.
Definition validator.c:760

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

Referenced by tls_new_handshake().

◆ tls_new_finished()

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

Receive new Finished handshake record.

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

Definition at line 2653 of file tls.c.

2654 {
2655 struct tls_session *session = tls->session;
2656 struct digest_algorithm *digest = tls->handshake_digest;
2657 const struct {
2658 uint8_t verify_data[ sizeof ( tls->verify.server ) ];
2659 char next[0];
2660 } __attribute__ (( packed )) *finished = data;
2661 uint8_t digest_out[ digest->digestsize ];
2662
2663 /* Sanity check */
2664 if ( sizeof ( *finished ) != len ) {
2665 DBGC ( tls, "TLS %p received overlength Finished\n", tls );
2666 DBGC_HD ( tls, data, len );
2667 return -EINVAL_FINISHED;
2668 }
2669
2670 /* Verify data */
2671 tls_verify_handshake ( tls, digest_out );
2672 tls_prf_label ( tls, &tls->master_secret, sizeof ( tls->master_secret ),
2673 tls->verify.server, sizeof ( tls->verify.server ),
2674 "server finished", digest_out, sizeof ( digest_out ) );
2675 if ( memcmp ( tls->verify.server, finished->verify_data,
2676 sizeof ( tls->verify.server ) ) != 0 ) {
2677 DBGC ( tls, "TLS %p verification failed\n", tls );
2678 return -EPERM_VERIFY;
2679 }
2680
2681 /* Mark server as finished */
2682 pending_put ( &tls->server.negotiation );
2683
2684 /* If we are resuming a session (i.e. if the server Finished
2685 * arrives before the client Finished is sent), then schedule
2686 * transmission of Change Cipher and Finished.
2687 */
2688 if ( is_pending ( &tls->client.negotiation ) ) {
2690 tls_tx_resume ( tls );
2691 }
2692
2693 /* Record session ID, ticket, and master secret, if applicable */
2694 if ( tls->session_id_len || tls->new_session_ticket_len ) {
2695 memcpy ( session->master_secret, tls->master_secret,
2696 sizeof ( session->master_secret ) );
2698 }
2699 if ( tls->session_id_len ) {
2700 session->id_len = tls->session_id_len;
2701 memcpy ( session->id, tls->session_id, sizeof ( session->id ) );
2702 }
2703 if ( tls->new_session_ticket_len ) {
2704 free ( session->ticket );
2705 session->ticket = tls->new_session_ticket;
2706 session->ticket_len = tls->new_session_ticket_len;
2707 tls->new_session_ticket = NULL;
2708 tls->new_session_ticket_len = 0;
2709 }
2710
2711 /* Move to end of session's connection list and allow other
2712 * connections to start making progress.
2713 */
2714 list_del ( &tls->list );
2715 list_add_tail ( &tls->list, &session->conn );
2716 tls_tx_resume_all ( session );
2717
2718 /* Send notification of a window change */
2720
2721 return 0;
2722}
#define list_add_tail(new, head)
Add a new entry to the tail of a list.
Definition list.h:94
uint8_t id[32]
Session ID.
Definition tls.h:356
size_t id_len
Length of session ID.
Definition tls.h:358
uint8_t master_secret[48]
Master secret.
Definition tls.h:364
uint8_t server[12]
Server verification data.
Definition tls.h:170
#define EINVAL_FINISHED
Definition tls.c:82
#define EPERM_VERIFY
Definition tls.c:170
@ TLS_TX_FINISHED
Definition tls.h:186
@ TLS_TX_CHANGE_CIPHER
Definition tls.h:185
void xfer_window_changed(struct interface *intf)
Report change of flow control window.
Definition xfer.c:147

References __attribute__, tls_connection::client, tls_session::conn, data, DBGC, DBGC_HD, digest_algorithm::digestsize, EINVAL_FINISHED, EPERM_VERIFY, tls_connection::extended_master_secret, tls_session::extended_master_secret, free, tls_connection::handshake_digest, tls_session::id, tls_session::id_len, is_pending(), len, tls_connection::list, list_add_tail, list_del, tls_connection::master_secret, tls_session::master_secret, memcmp(), memcpy(), tls_client::negotiation, tls_server::negotiation, tls_connection::new_session_ticket, tls_connection::new_session_ticket_len, next, NULL, tls_tx::pending, pending_put(), tls_connection::plainstream, tls_connection::server, tls_verify_data::server, tls_connection::session, tls_connection::session_id, tls_connection::session_id_len, tls_session::ticket, tls_session::ticket_len, tls_prf_label, TLS_TX_CHANGE_CIPHER, TLS_TX_FINISHED, tls_tx_resume(), tls_tx_resume_all(), tls_verify_handshake(), tls_connection::tx, tls_connection::verify, and xfer_window_changed().

Referenced by tls_new_handshake().

◆ tls_new_handshake()

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

Receive new Handshake record.

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

Definition at line 2731 of file tls.c.

2732 {
2733 size_t remaining;
2734 int rc;
2735
2736 while ( ( remaining = iob_len ( iobuf ) ) ) {
2737 const struct {
2738 uint8_t type;
2740 uint8_t payload[0];
2741 } __attribute__ (( packed )) *handshake = iobuf->data;
2742 const void *payload;
2743 size_t payload_len;
2744 size_t record_len;
2745
2746 /* Parse header */
2747 if ( sizeof ( *handshake ) > remaining ) {
2748 /* Leave remaining fragment unconsumed */
2749 break;
2750 }
2751 payload_len = tls_uint24 ( &handshake->length );
2752 if ( payload_len > ( remaining - sizeof ( *handshake ) ) ) {
2753 /* Leave remaining fragment unconsumed */
2754 break;
2755 }
2756 payload = &handshake->payload;
2757 record_len = ( sizeof ( *handshake ) + payload_len );
2758
2759 /* Handle payload */
2760 switch ( handshake->type ) {
2761 case TLS_HELLO_REQUEST:
2762 rc = tls_new_hello_request ( tls, payload,
2763 payload_len );
2764 break;
2765 case TLS_SERVER_HELLO:
2766 rc = tls_new_server_hello ( tls, payload, payload_len );
2767 break;
2769 rc = tls_new_session_ticket ( tls, payload,
2770 payload_len );
2771 break;
2772 case TLS_CERTIFICATE:
2773 rc = tls_new_certificate ( tls, payload, payload_len );
2774 break;
2776 rc = tls_new_server_key_exchange ( tls, payload,
2777 payload_len );
2778 break;
2780 rc = tls_new_certificate_request ( tls, payload,
2781 payload_len );
2782 break;
2784 rc = tls_new_server_hello_done ( tls, payload,
2785 payload_len );
2786 break;
2787 case TLS_FINISHED:
2788 rc = tls_new_finished ( tls, payload, payload_len );
2789 break;
2790 default:
2791 DBGC ( tls, "TLS %p ignoring handshake type %d\n",
2792 tls, handshake->type );
2793 rc = 0;
2794 break;
2795 }
2796
2797 /* Add to handshake digest (except for Hello Requests,
2798 * which are explicitly excluded).
2799 */
2800 if ( handshake->type != TLS_HELLO_REQUEST )
2801 tls_add_handshake ( tls, handshake, record_len );
2802
2803 /* Abort on failure */
2804 if ( rc != 0 )
2805 return rc;
2806
2807 /* Move to next handshake record */
2808 iob_pull ( iobuf, record_len );
2809 }
2810
2811 return 0;
2812}
static int tls_new_finished(struct tls_connection *tls, const void *data, size_t len)
Receive new Finished handshake record.
Definition tls.c:2653
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:2152
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:2557
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:2354
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:2121
static int tls_new_certificate(struct tls_connection *tls, const void *data, size_t len)
Receive new Certificate handshake record.
Definition tls.c:2486
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:2617
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:2526
#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 2821 of file tls.c.

2822 {
2823
2824 /* RFC4346 says that we should just ignore unknown record types */
2825 iob_pull ( iobuf, iob_len ( iobuf ) );
2826 return 0;
2827}

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

2837 {
2838 struct io_buffer *iobuf;
2839 int rc;
2840
2841 /* Fail unless we are ready to receive data */
2842 if ( ! tls_ready ( tls ) )
2843 return -ENOTCONN;
2844
2845 /* Deliver each I/O buffer in turn */
2846 while ( ( iobuf = list_first_entry ( rx_data, struct io_buffer,
2847 list ) ) ) {
2848 list_del ( &iobuf->list );
2849 if ( ( rc = xfer_deliver_iob ( &tls->plainstream,
2850 iobuf ) ) != 0 ) {
2851 DBGC ( tls, "TLS %p could not deliver data: "
2852 "%s\n", tls, strerror ( rc ) );
2853 return rc;
2854 }
2855 }
2856
2857 return 0;
2858}
#define ENOTCONN
The socket is not connected.
Definition errno.h:570
#define list_first_entry(list, type, member)
Get the container of the first entry in a list.
Definition list.h:334

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

Referenced by tls_new_record().

◆ tls_new_record()

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

Receive new record.

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

Definition at line 2868 of file tls.c.

2869 {
2870 int ( * handler ) ( struct tls_connection *tls,
2871 struct io_buffer *iobuf );
2872 struct io_buffer *tmp = NULL;
2873 struct io_buffer **iobuf;
2874 int rc;
2875
2876 /* Deliver data records as-is to the plainstream interface */
2877 if ( type == TLS_TYPE_DATA )
2878 return tls_new_data ( tls, rx_data );
2879
2880 /* Determine handler and fragment buffer */
2881 iobuf = &tmp;
2882 switch ( type ) {
2884 handler = tls_new_change_cipher;
2885 break;
2886 case TLS_TYPE_ALERT:
2887 handler = tls_new_alert;
2888 break;
2889 case TLS_TYPE_HANDSHAKE:
2890 handler = tls_new_handshake;
2891 iobuf = &tls->rx.handshake;
2892 break;
2893 default:
2894 DBGC ( tls, "TLS %p unknown record type %d\n", tls, type );
2895 handler = tls_new_unknown;
2896 break;
2897 }
2898
2899 /* Merge into a single I/O buffer */
2900 if ( *iobuf )
2901 list_add ( &(*iobuf)->list, rx_data );
2902 *iobuf = iob_concatenate ( rx_data );
2903 if ( ! *iobuf ) {
2904 DBGC ( tls, "TLS %p could not concatenate non-data record "
2905 "type %d\n", tls, type );
2907 goto err_concatenate;
2908 }
2909
2910 /* Handle record */
2911 if ( ( rc = handler ( tls, *iobuf ) ) != 0 )
2912 goto err_handle;
2913
2914 /* Discard I/O buffer if empty */
2915 if ( ! iob_len ( *iobuf ) ) {
2916 free_iob ( *iobuf );
2917 *iobuf = NULL;
2918 }
2919
2920 /* Sanity check */
2921 assert ( tmp == NULL );
2922
2923 return 0;
2924
2925 err_handle:
2926 free_iob ( *iobuf );
2927 *iobuf = NULL;
2928 err_concatenate:
2929 return rc;
2930}
struct io_buffer * iob_concatenate(struct list_head *list)
Concatenate I/O buffers into a single buffer.
Definition iobuf.c:250
#define list_add(new, head)
Add a new entry to the head of a list.
Definition list.h:70
static int tls_new_change_cipher(struct tls_connection *tls, struct io_buffer *iobuf)
Receive new Change Cipher record.
Definition tls.c:2036
#define ENOMEM_RX_CONCAT
Definition tls.c:142
static int tls_new_unknown(struct tls_connection *tls __unused, struct io_buffer *iobuf)
Receive new unknown record.
Definition tls.c:2821
static int tls_new_data(struct tls_connection *tls, struct list_head *rx_data)
Receive new data record.
Definition tls.c:2836
static int tls_new_handshake(struct tls_connection *tls, struct io_buffer *iobuf)
Receive new Handshake record.
Definition tls.c:2731
static int tls_new_alert(struct tls_connection *tls, struct io_buffer *iobuf)
Receive new Alert record.
Definition tls.c:2071
#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 2946 of file tls.c.

2947 {
2948 struct tls_cipher_suite *suite = cipherspec->suite;
2949 struct digest_algorithm *digest = suite->digest;
2950
2951 hmac_init ( digest, ctx, cipherspec->mac_secret, suite->mac_len );
2952 hmac_update ( digest, ctx, authhdr, sizeof ( *authhdr ) );
2953}

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

2964 {
2965 struct digest_algorithm *digest = cipherspec->suite->digest;
2966
2967 hmac_update ( digest, ctx, data, len );
2968}

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

2978 {
2979 struct digest_algorithm *digest = cipherspec->suite->digest;
2980
2981 hmac_final ( digest, ctx, hmac );
2982}

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

2995 {
2996 struct digest_algorithm *digest = cipherspec->suite->digest;
2997 uint8_t ctx[ hmac_ctxsize ( digest ) ];
2998
2999 tls_hmac_init ( cipherspec, ctx, authhdr );
3000 tls_hmac_update ( cipherspec, ctx, data, len );
3001 tls_hmac_final ( cipherspec, ctx, hmac );
3002}
static void tls_hmac_init(struct tls_cipherspec *cipherspec, void *ctx, struct tls_auth_header *authhdr)
Initialise HMAC.
Definition tls.c:2946
static void tls_hmac_final(struct tls_cipherspec *cipherspec, void *ctx, void *hmac)
Finalise HMAC.
Definition tls.c:2977
static void tls_hmac_update(struct tls_cipherspec *cipherspec, void *ctx, const void *data, size_t len)
Update HMAC.
Definition tls.c:2963

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

3014 {
3015 struct digest_algorithm *digest = cipherspec->suite->digest;
3016 uint8_t ctx[ hmac_ctxsize ( digest ) ];
3017 struct io_buffer *iobuf;
3018
3019 tls_hmac_init ( cipherspec, ctx, authhdr );
3020 list_for_each_entry ( iobuf, list, list ) {
3021 tls_hmac_update ( cipherspec, ctx, iobuf->data,
3022 iob_len ( iobuf ) );
3023 }
3024 tls_hmac_final ( cipherspec, ctx, hmac );
3025}

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

3034 {
3035 struct tls_cipherspec *cipherspec = &tls->tx.cipherspec.active;
3036 struct tls_cipher_suite *suite = cipherspec->suite;
3037 struct cipher_algorithm *cipher = suite->cipher;
3038 struct tls_header *tlshdr;
3039 unsigned int count;
3040 size_t each;
3041
3042 /* Calculate number of records (allowing for zero-length records) */
3043 count = ( len ? ( ( len + TLS_TX_BUFSIZE - 1 ) / TLS_TX_BUFSIZE ) : 1 );
3044
3045 /* Calculate maximum additional length per record */
3046 each = ( sizeof ( *tlshdr ) + suite->record_iv_len + suite->mac_len +
3047 ( is_block_cipher ( cipher ) ? cipher->blocksize : 0 ) +
3048 cipher->authsize );
3049
3050 /* Calculate maximum total additional length */
3051 return ( count * each );
3052}
static unsigned int count
Number of entries.
Definition dwmac.h:220

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

Referenced by tls_alloc_iob(), and tls_send_record().

◆ tls_verify_padding()

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

Verify block padding.

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

Definition at line 3257 of file tls.c.

3258 {
3259 uint8_t *padding;
3260 unsigned int pad;
3261 unsigned int i;
3262 size_t len;
3263
3264 /* Extract and verify padding */
3265 padding = ( iobuf->tail - 1 );
3266 pad = *padding;
3267 len = ( pad + 1 );
3268 if ( len > iob_len ( iobuf ) ) {
3269 DBGC ( tls, "TLS %p received underlength padding\n", tls );
3270 DBGC_HD ( tls, iobuf->data, iob_len ( iobuf ) );
3271 return -EINVAL_PADDING;
3272 }
3273 for ( i = 0 ; i < pad ; i++ ) {
3274 if ( *(--padding) != pad ) {
3275 DBGC ( tls, "TLS %p received bad padding\n", tls );
3276 DBGC_HD ( tls, iobuf->data, iob_len ( iobuf ) );
3277 return -EINVAL_PADDING;
3278 }
3279 }
3280
3281 return len;
3282}
u32 pad[9]
Padding.
Definition ar9003_mac.h:23
void * tail
End of data.
Definition iobuf.h:55
#define EINVAL_PADDING
Definition tls.c:94

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

3294 {
3295 struct tls_cipherspec *cipherspec = &tls->rx.cipherspec.active;
3296 struct tls_cipher_suite *suite = cipherspec->suite;
3297 struct cipher_algorithm *cipher = suite->cipher;
3298 struct digest_algorithm *digest = suite->digest;
3299 size_t len = ntohs ( tlshdr->length );
3300 struct {
3301 uint8_t fixed[suite->fixed_iv_len];
3302 uint8_t record[suite->record_iv_len];
3303 } __attribute__ (( packed )) iv;
3304 struct tls_auth_header authhdr;
3305 uint8_t verify_mac[digest->digestsize];
3306 uint8_t verify_auth[cipher->authsize];
3307 struct io_buffer *first;
3308 struct io_buffer *last;
3309 struct io_buffer *iobuf;
3310 void *mac;
3311 void *auth;
3312 size_t check_len;
3313 int pad_len;
3314 int rc;
3315
3316 /* Locate first and last data buffers */
3317 assert ( ! list_empty ( rx_data ) );
3318 first = list_first_entry ( rx_data, struct io_buffer, list );
3319 last = list_last_entry ( rx_data, struct io_buffer, list );
3320
3321 /* Extract initialisation vector */
3322 if ( iob_len ( first ) < sizeof ( iv.record ) ) {
3323 DBGC ( tls, "TLS %p received underlength IV\n", tls );
3324 DBGC_HD ( tls, first->data, iob_len ( first ) );
3325 return -EINVAL_IV;
3326 }
3327 memcpy ( iv.fixed, cipherspec->fixed_iv, sizeof ( iv.fixed ) );
3328 memcpy ( iv.record, first->data, sizeof ( iv.record ) );
3329 iob_pull ( first, sizeof ( iv.record ) );
3330 len -= sizeof ( iv.record );
3331
3332 /* Extract unencrypted authentication tag */
3333 if ( iob_len ( last ) < cipher->authsize ) {
3334 DBGC ( tls, "TLS %p received underlength authentication tag\n",
3335 tls );
3336 DBGC_HD ( tls, last->data, iob_len ( last ) );
3337 return -EINVAL_MAC;
3338 }
3339 iob_unput ( last, cipher->authsize );
3340 len -= cipher->authsize;
3341 auth = last->tail;
3342
3343 /* Construct authentication data */
3344 authhdr.seq = cpu_to_be64 ( tls->rx.seq );
3345 authhdr.header.type = tlshdr->type;
3346 authhdr.header.version = tlshdr->version;
3347 authhdr.header.length = htons ( len );
3348
3349 /* Set initialisation vector */
3350 cipher_setiv ( cipher, cipherspec->cipher_ctx, &iv, sizeof ( iv ) );
3351
3352 /* Process authentication data, if applicable */
3353 if ( is_auth_cipher ( cipher ) ) {
3354 cipher_decrypt ( cipher, cipherspec->cipher_ctx, &authhdr,
3355 NULL, sizeof ( authhdr ) );
3356 }
3357
3358 /* Decrypt the received data */
3359 check_len = 0;
3360 list_for_each_entry ( iobuf, &tls->rx.data, list ) {
3361 cipher_decrypt ( cipher, cipherspec->cipher_ctx,
3362 iobuf->data, iobuf->data, iob_len ( iobuf ) );
3363 check_len += iob_len ( iobuf );
3364 }
3365 assert ( check_len == len );
3366
3367 /* Strip block padding, if applicable */
3368 if ( is_block_cipher ( cipher ) ) {
3369 pad_len = tls_verify_padding ( tls, last );
3370 if ( pad_len < 0 ) {
3371 /* Assume zero padding length to avoid timing attacks */
3372 pad_len = 0;
3373 }
3374 iob_unput ( last, pad_len );
3375 len -= pad_len;
3376 }
3377
3378 /* Extract decrypted MAC */
3379 if ( iob_len ( last ) < suite->mac_len ) {
3380 DBGC ( tls, "TLS %p received underlength MAC\n", tls );
3381 DBGC_HD ( tls, last->data, iob_len ( last ) );
3382 return -EINVAL_MAC;
3383 }
3384 iob_unput ( last, suite->mac_len );
3385 len -= suite->mac_len;
3386 mac = last->tail;
3387
3388 /* Dump received data */
3389 DBGC2 ( tls, "Received plaintext data:\n" );
3390 check_len = 0;
3391 list_for_each_entry ( iobuf, rx_data, list ) {
3392 DBGC2_HD ( tls, iobuf->data, iob_len ( iobuf ) );
3393 check_len += iob_len ( iobuf );
3394 }
3395 assert ( check_len == len );
3396
3397 /* Generate MAC */
3398 authhdr.header.length = htons ( len );
3399 if ( suite->mac_len )
3400 tls_hmac_list ( cipherspec, &authhdr, rx_data, verify_mac );
3401
3402 /* Generate authentication tag */
3403 cipher_auth ( cipher, cipherspec->cipher_ctx, verify_auth );
3404
3405 /* Verify MAC */
3406 if ( memcmp ( mac, verify_mac, suite->mac_len ) != 0 ) {
3407 DBGC ( tls, "TLS %p failed MAC verification\n", tls );
3408 return -EINVAL_MAC;
3409 }
3410
3411 /* Verify authentication tag */
3412 if ( memcmp ( auth, verify_auth, cipher->authsize ) != 0 ) {
3413 DBGC ( tls, "TLS %p failed authentication tag verification\n",
3414 tls );
3415 return -EINVAL_MAC;
3416 }
3417
3418 /* Process plaintext record */
3419 if ( ( rc = tls_new_record ( tls, tlshdr->type, rx_data ) ) != 0 )
3420 return rc;
3421
3422 return 0;
3423}
#define cipher_decrypt(cipher, ctx, src, dst, len)
Definition crypto.h:261
#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:90
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:3012
#define EINVAL_MAC
Definition tls.c:102
static int tls_verify_padding(struct tls_connection *tls, struct io_buffer *iobuf)
Verify block padding.
Definition tls.c:3257
static int tls_new_record(struct tls_connection *tls, unsigned int type, struct list_head *rx_data)
Receive new record.
Definition tls.c:2868

References __attribute__, tls_cipherspec_pair::active, assert, cipher_algorithm::authsize, tls_cipher_suite::cipher, cipher_auth(), tls_cipherspec::cipher_ctx, cipher_decrypt, cipher_setiv(), tls_rx::cipherspec, cpu_to_be64, io_buffer::data, tls_rx::data, DBGC, DBGC2, DBGC2_HD, DBGC_HD, tls_cipher_suite::digest, digest_algorithm::digestsize, EINVAL_IV, EINVAL_MAC, first, fixed, tls_cipherspec::fixed_iv, tls_cipher_suite::fixed_iv_len, tls_auth_header::header, htons, iob_len(), iob_pull, iob_unput, is_auth_cipher(), is_block_cipher(), iv, len, tls_header::length, io_buffer::list, list_empty, list_first_entry, list_for_each_entry, list_last_entry, mac, tls_cipher_suite::mac_len, memcmp(), memcpy(), ntohs, NULL, pad_len, rc, tls_cipher_suite::record_iv_len, tls_connection::rx, tls_auth_header::seq, tls_rx::seq, 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 3438 of file tls.c.

3438 {
3439
3440 /* Block window unless we are ready to accept data */
3441 if ( ! tls_ready ( tls ) )
3442 return 0;
3443
3444 return xfer_window ( &tls->cipherstream );
3445}
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 3455 of file tls.c.

3457 {
3458 int rc;
3459
3460 /* Refuse unless we are ready to accept data */
3461 if ( ! tls_ready ( tls ) ) {
3462 rc = -ENOTCONN;
3463 goto done;
3464 }
3465
3466 /* Send data record */
3467 if ( ( rc = tls_send_record ( tls, TLS_TYPE_DATA,
3468 iob_disown ( iobuf ) ) ) != 0 )
3469 goto done;
3470
3471 done:
3472 free_iob ( iobuf );
3473 return rc;
3474}
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 3483 of file tls.c.

3484 {
3485
3486 /* Return cipherstream or validator progress as applicable */
3487 if ( is_pending ( &tls->server.validation ) ) {
3488 return job_progress ( &tls->server.validator, progress );
3489 } else {
3490 return job_progress ( &tls->cipherstream, progress );
3491 }
3492}
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 3523 of file tls.c.

3523 {
3524 struct tls_cipherspec *cipherspec = &tls->rx.cipherspec.active;
3525 struct cipher_algorithm *cipher = cipherspec->suite->cipher;
3526 size_t iv_len = cipherspec->suite->record_iv_len;
3527 size_t data_len = ntohs ( tls->rx.header.length );
3528 size_t remaining = data_len;
3529 size_t frag_len;
3530 size_t reserve;
3531 struct io_buffer *iobuf;
3532 struct io_buffer *tmp;
3533 int rc;
3534
3535 /* Sanity check */
3536 assert ( ( TLS_RX_BUFSIZE % cipher->alignsize ) == 0 );
3537
3538 /* Calculate alignment reservation at start of first data buffer */
3539 reserve = ( ( -iv_len ) & ( cipher->alignsize - 1 ) );
3540 remaining += reserve;
3541
3542 /* Allocate data buffers now that we know the length */
3543 assert ( list_empty ( &tls->rx.data ) );
3544 while ( remaining ) {
3545
3546 /* Calculate fragment length. Ensure that no block is
3547 * smaller than TLS_RX_MIN_BUFSIZE (by increasing the
3548 * allocation length if necessary).
3549 */
3550 frag_len = remaining;
3551 if ( frag_len > TLS_RX_BUFSIZE )
3552 frag_len = TLS_RX_BUFSIZE;
3553 remaining -= frag_len;
3554 if ( remaining < TLS_RX_MIN_BUFSIZE ) {
3555 frag_len += remaining;
3556 remaining = 0;
3557 }
3558
3559 /* Allocate buffer */
3560 iobuf = alloc_iob_raw ( frag_len, TLS_RX_ALIGN, 0 );
3561 if ( ! iobuf ) {
3562 DBGC ( tls, "TLS %p could not allocate %zd of %zd "
3563 "bytes for receive buffer\n", tls,
3564 remaining, data_len );
3565 rc = -ENOMEM_RX_DATA;
3566 goto err;
3567 }
3568
3569 /* Ensure tailroom is exactly what we asked for. This
3570 * will result in unaligned I/O buffers when the
3571 * fragment length is unaligned, which can happen only
3572 * before we switch to using a block cipher.
3573 */
3574 iob_reserve ( iobuf, ( iob_tailroom ( iobuf ) - frag_len ) );
3575
3576 /* Ensure first buffer length will be aligned to a
3577 * multiple of the cipher alignment size after
3578 * stripping the record IV.
3579 */
3580 iob_reserve ( iobuf, reserve );
3581 reserve = 0;
3582
3583 /* Add I/O buffer to list */
3584 list_add_tail ( &iobuf->list, &tls->rx.data );
3585 }
3586
3587 /* Move to data state */
3588 tls->rx.state = TLS_RX_DATA;
3589
3590 return 0;
3591
3592 err:
3593 list_for_each_entry_safe ( iobuf, tmp, &tls->rx.data, list ) {
3594 list_del ( &iobuf->list );
3595 free_iob ( iobuf );
3596 }
3597 return rc;
3598}
struct io_buffer * alloc_iob_raw(size_t len, size_t align, size_t offset)
Allocate I/O buffer with specified alignment and offset.
Definition iobuf.c:49
static size_t iob_tailroom(struct io_buffer *iobuf)
Calculate available space at end of an I/O buffer.
Definition iobuf.h:180
size_t alignsize
Alignment size.
Definition crypto.h:73
enum tls_rx_state state
State machine current state.
Definition tls.h:391
struct tls_header header
Current received record header.
Definition tls.h:393
#define ENOMEM_RX_DATA
Definition tls.c:138
#define TLS_RX_MIN_BUFSIZE
Minimum RX I/O buffer size.
Definition tls.h:511
#define TLS_RX_ALIGN
RX I/O buffer alignment.
Definition tls.h:514
@ TLS_RX_DATA
Definition tls.h:176
#define TLS_RX_BUFSIZE
RX I/O buffer size.
Definition tls.h:503
uint32_t data_len
Microcode data size (or 0 to indicate 2000 bytes)
Definition ucode.h:15

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

Referenced by tls_cipherstream_deliver().

◆ tls_newdata_process_data()

int tls_newdata_process_data ( struct tls_connection * tls)
static

Handle received TLS data payload.

Parameters
tlsTLS connection
Return values
rcReturned status code

Definition at line 3606 of file tls.c.

3606 {
3607 struct io_buffer *iobuf;
3608 int rc;
3609
3610 /* Move current buffer to end of list */
3611 iobuf = list_first_entry ( &tls->rx.data, struct io_buffer, list );
3612 list_del ( &iobuf->list );
3613 list_add_tail ( &iobuf->list, &tls->rx.data );
3614
3615 /* Continue receiving data if any space remains */
3616 iobuf = list_first_entry ( &tls->rx.data, struct io_buffer, list );
3617 if ( iob_tailroom ( iobuf ) )
3618 return 0;
3619
3620 /* Process record */
3621 if ( ( rc = tls_new_ciphertext ( tls, &tls->rx.header,
3622 &tls->rx.data ) ) != 0 )
3623 return rc;
3624
3625 /* Increment RX sequence number */
3626 tls->rx.seq += 1;
3627
3628 /* Return to header state */
3629 assert ( list_empty ( &tls->rx.data ) );
3630 tls->rx.state = TLS_RX_HEADER;
3631 iob_unput ( &tls->rx.iobuf, sizeof ( tls->rx.header ) );
3632
3633 return 0;
3634}
struct io_buffer iobuf
Current received record header (static I/O buffer)
Definition tls.h:395
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:3292
@ TLS_RX_HEADER
Definition tls.h:175

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

3642 {
3643
3644 /* Open window until we are ready to accept data */
3645 if ( ! tls_ready ( tls ) )
3646 return -1UL;
3647
3648 return xfer_window ( &tls->plainstream );
3649}

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

3661 {
3662 size_t frag_len;
3663 int ( * process ) ( struct tls_connection *tls );
3664 struct io_buffer *dest;
3665 int rc;
3666
3667 while ( iob_len ( iobuf ) ) {
3668
3669 /* Select buffer according to current state */
3670 switch ( tls->rx.state ) {
3671 case TLS_RX_HEADER:
3672 dest = &tls->rx.iobuf;
3674 break;
3675 case TLS_RX_DATA:
3676 dest = list_first_entry ( &tls->rx.data,
3677 struct io_buffer, list );
3678 assert ( dest != NULL );
3680 break;
3681 default:
3682 assert ( 0 );
3684 goto done;
3685 }
3686
3687 /* Copy data portion to buffer */
3688 frag_len = iob_len ( iobuf );
3689 if ( frag_len > iob_tailroom ( dest ) )
3690 frag_len = iob_tailroom ( dest );
3691 memcpy ( iob_put ( dest, frag_len ), iobuf->data, frag_len );
3692 iob_pull ( iobuf, frag_len );
3693
3694 /* Process data if buffer is now full */
3695 if ( iob_tailroom ( dest ) == 0 ) {
3696 if ( ( rc = process ( tls ) ) != 0 ) {
3697 tls_close ( tls, rc );
3698 goto done;
3699 }
3700 }
3701 }
3702 rc = 0;
3703
3704 done:
3705 free_iob ( iobuf );
3706 return rc;
3707}
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:98
static int tls_newdata_process_data(struct tls_connection *tls)
Handle received TLS data payload.
Definition tls.c:3606
static int tls_newdata_process_header(struct tls_connection *tls)
Handle received TLS header.
Definition tls.c:3523

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

3738 {
3739 struct tls_session *session = tls->session;
3740 struct x509_certificate *cert;
3741
3742 /* Mark validation as complete */
3743 pending_put ( &tls->server.validation );
3744
3745 /* Close validator interface */
3746 intf_restart ( &tls->server.validator, rc );
3747
3748 /* Check for validation failure */
3749 if ( rc != 0 ) {
3750 DBGC ( tls, "TLS %p certificate validation failed: %s\n",
3751 tls, strerror ( rc ) );
3752 goto err;
3753 }
3754 DBGC ( tls, "TLS %p certificate validation succeeded\n", tls );
3755
3756 /* Extract first certificate */
3757 cert = x509_first ( tls->server.chain );
3758 assert ( cert != NULL );
3759
3760 /* Verify server name */
3761 if ( ( rc = x509_check_name ( cert, session->name ) ) != 0 ) {
3762 DBGC ( tls, "TLS %p server certificate does not match %s: %s\n",
3763 tls, session->name, strerror ( rc ) );
3764 goto err;
3765 }
3766
3767 /* Extract the now trusted server public key */
3768 memcpy ( &tls->server.key, &cert->subject.public_key.raw,
3769 sizeof ( tls->server.key ) );
3770
3771 /* Schedule transmission of applicable handshake messages */
3775 if ( tls->client.chain ) {
3777 if ( ! list_empty ( &tls->client.chain->links ) )
3779 }
3780 tls_tx_resume ( tls );
3781
3782 return;
3783
3784 err:
3785 tls_close ( tls, rc );
3786 return;
3787}
void intf_restart(struct interface *intf, int rc)
Shut down and restart an object interface.
Definition interface.c:344
struct x509_subject subject
Subject.
Definition x509.h:245
struct asn1_cursor raw
Raw public key information.
Definition x509.h:52
struct x509_public_key public_key
Public key information.
Definition x509.h:66
@ TLS_TX_CLIENT_KEY_EXCHANGE
Definition tls.h:183
@ TLS_TX_CERTIFICATE_VERIFY
Definition tls.h:184
@ TLS_TX_CERTIFICATE
Definition tls.h:182
int x509_check_name(struct x509_certificate *cert, const char *name)
Check X.509 certificate name.
Definition x509.c:1564

References assert, tls_client::chain, tls_server::chain, tls_connection::client, DBGC, intf_restart(), tls_server::key, x509_chain::links, list_empty, memcpy(), tls_session::name, NULL, tls_tx::pending, pending_put(), x509_subject::public_key, x509_public_key::raw, rc, tls_connection::server, tls_connection::session, strerror(), x509_certificate::subject, tls_close(), 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, tls_server::validator, x509_check_name(), and x509_first().

◆ tls_tx_step()

void tls_tx_step ( struct tls_connection * tls)
static

TLS TX state machine.

Parameters
tlsTLS connection

Definition at line 3811 of file tls.c.

3811 {
3812 struct tls_session *session = tls->session;
3813 struct tls_connection *conn;
3814 int rc;
3815
3816 /* Wait for cipherstream to become ready */
3817 if ( ! xfer_window ( &tls->cipherstream ) )
3818 return;
3819
3820 /* Send first pending transmission */
3821 if ( tls->tx.pending & TLS_TX_CLIENT_HELLO ) {
3822 /* Serialise server negotiations within a session, to
3823 * provide a consistent view of session IDs and
3824 * session tickets.
3825 */
3826 list_for_each_entry ( conn, &session->conn, list ) {
3827 if ( conn == tls )
3828 break;
3829 if ( is_pending ( &conn->server.negotiation ) )
3830 return;
3831 }
3832 /* Record or generate session ID and associated master secret */
3833 if ( session->id_len ) {
3834 /* Attempt to resume an existing session */
3835 memcpy ( tls->session_id, session->id,
3836 sizeof ( tls->session_id ) );
3839 sizeof ( tls->master_secret ) );
3840 } else {
3841 /* No existing session: use a random session ID */
3842 assert ( sizeof ( tls->session_id ) ==
3843 sizeof ( tls->client.random ) );
3844 memcpy ( tls->session_id, &tls->client.random,
3845 sizeof ( tls->session_id ) );
3846 tls->session_id_len = sizeof ( tls->session_id );
3847 }
3848 /* Send Client Hello */
3849 if ( ( rc = tls_send_client_hello ( tls ) ) != 0 ) {
3850 DBGC ( tls, "TLS %p could not send Client Hello: %s\n",
3851 tls, strerror ( rc ) );
3852 goto err;
3853 }
3855 } else if ( tls->tx.pending & TLS_TX_CERTIFICATE ) {
3856 /* Send Certificate */
3857 if ( ( rc = tls_send_certificate ( tls ) ) != 0 ) {
3858 DBGC ( tls, "TLS %p cold not send Certificate: %s\n",
3859 tls, strerror ( rc ) );
3860 goto err;
3861 }
3863 } else if ( tls->tx.pending & TLS_TX_CLIENT_KEY_EXCHANGE ) {
3864 /* Send Client Key Exchange */
3865 if ( ( rc = tls_send_client_key_exchange ( tls ) ) != 0 ) {
3866 DBGC ( tls, "TLS %p could not send Client Key "
3867 "Exchange: %s\n", tls, strerror ( rc ) );
3868 goto err;
3869 }
3871 } else if ( tls->tx.pending & TLS_TX_CERTIFICATE_VERIFY ) {
3872 /* Send Certificate Verify */
3873 if ( ( rc = tls_send_certificate_verify ( tls ) ) != 0 ) {
3874 DBGC ( tls, "TLS %p could not send Certificate "
3875 "Verify: %s\n", tls, strerror ( rc ) );
3876 goto err;
3877 }
3879 } else if ( tls->tx.pending & TLS_TX_CHANGE_CIPHER ) {
3880 /* Send Change Cipher, and then change the cipher in use */
3881 if ( ( rc = tls_send_change_cipher ( tls ) ) != 0 ) {
3882 DBGC ( tls, "TLS %p could not send Change Cipher: "
3883 "%s\n", tls, strerror ( rc ) );
3884 goto err;
3885 }
3886 if ( ( rc = tls_change_cipher ( tls,
3887 &tls->tx.cipherspec ) ) != 0 ){
3888 DBGC ( tls, "TLS %p could not activate TX cipher: "
3889 "%s\n", tls, strerror ( rc ) );
3890 goto err;
3891 }
3892 tls->tx.seq = 0;
3894 } else if ( tls->tx.pending & TLS_TX_FINISHED ) {
3895 /* Send Finished */
3896 if ( ( rc = tls_send_finished ( tls ) ) != 0 ) {
3897 DBGC ( tls, "TLS %p could not send Finished: %s\n",
3898 tls, strerror ( rc ) );
3899 goto err;
3900 }
3901 tls->tx.pending &= ~TLS_TX_FINISHED;
3902 }
3903
3904 /* Reschedule process if pending transmissions remain,
3905 * otherwise send notification of a window change.
3906 */
3907 if ( tls->tx.pending ) {
3908 tls_tx_resume ( tls );
3909 } else {
3911 }
3912
3913 return;
3914
3915 err:
3916 tls_close ( tls, rc );
3917}
static int tls_send_certificate(struct tls_connection *tls)
Transmit Certificate record.
Definition tls.c:1364
static int tls_send_finished(struct tls_connection *tls)
Transmit Finished record.
Definition tls.c:1972
static int tls_send_client_hello(struct tls_connection *tls)
Transmit Client Hello record.
Definition tls.c:1353
static int tls_send_client_key_exchange(struct tls_connection *tls)
Transmit Client Key Exchange record.
Definition tls.c:1846
static int tls_send_change_cipher(struct tls_connection *tls)
Transmit Change Cipher record.
Definition tls.c:1955
static int tls_send_certificate_verify(struct tls_connection *tls)
Transmit Certificate Verify record.
Definition tls.c:1874

References assert, tls_tx::cipherspec, tls_connection::cipherstream, tls_connection::client, tls_session::conn, DBGC, tls_session::id, tls_session::id_len, is_pending(), tls_connection::list, list_for_each_entry, tls_connection::master_secret, tls_session::master_secret, memcpy(), tls_server::negotiation, tls_tx::pending, tls_connection::plainstream, tls_client::random, rc, tls_tx::seq, tls_connection::server, tls_connection::session, tls_connection::session_id, tls_connection::session_id_len, strerror(), tls_change_cipher(), tls_close(), tls_send_certificate(), tls_send_certificate_verify(), tls_send_change_cipher(), tls_send_client_hello(), tls_send_client_key_exchange(), tls_send_finished(), TLS_TX_CERTIFICATE, TLS_TX_CERTIFICATE_VERIFY, TLS_TX_CHANGE_CIPHER, TLS_TX_CLIENT_HELLO, TLS_TX_CLIENT_KEY_EXCHANGE, TLS_TX_FINISHED, tls_tx_resume(), tls_connection::tx, xfer_window(), and xfer_window_changed().

◆ tls_session()

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

Find or create session for TLS connection.

Parameters
tlsTLS connection
nameServer name
Return values
rcReturn status code

Definition at line 3937 of file tls.c.

3937 {
3938 struct tls_session *session;
3939 char *name_copy;
3940 int rc;
3941
3942 /* Find existing matching session, if any */
3943 list_for_each_entry ( session, &tls_sessions, list ) {
3944 if ( ( strcmp ( name, session->name ) == 0 ) &&
3945 ( tls->server.root == session->root ) &&
3946 ( tls->client.key == session->key ) ) {
3947 ref_get ( &session->refcnt );
3948 tls->session = session;
3949 DBGC ( tls, "TLS %p joining session %s\n", tls, name );
3950 return 0;
3951 }
3952 }
3953
3954 /* Create new session */
3955 session = zalloc ( sizeof ( *session ) + strlen ( name )
3956 + 1 /* NUL */ );
3957 if ( ! session ) {
3958 rc = -ENOMEM;
3959 goto err_alloc;
3960 }
3961 ref_init ( &session->refcnt, free_tls_session );
3962 name_copy = ( ( ( void * ) session ) + sizeof ( *session ) );
3963 strcpy ( name_copy, name );
3964 session->name = name_copy;
3965 session->root = x509_root_get ( tls->server.root );
3966 session->key = privkey_get ( tls->client.key );
3967 INIT_LIST_HEAD ( &session->conn );
3968 list_add ( &session->list, &tls_sessions );
3969
3970 /* Record session */
3971 tls->session = session;
3972
3973 DBGC ( tls, "TLS %p created session %s\n", tls, name );
3974 return 0;
3975
3976 ref_put ( &session->refcnt );
3977 err_alloc:
3978 return rc;
3979}
const char * name
Definition ath9k_hw.c:1986
static struct private_key * privkey_get(struct private_key *key)
Get reference to private key.
Definition privkey.h:31
#define ref_get(refcnt)
Get additional reference to object.
Definition refcnt.h:93
#define ref_init(refcnt, free)
Initialise a reference counter.
Definition refcnt.h:65
int strcmp(const char *first, const char *second)
Compare strings.
Definition string.c:174
char * strcpy(char *dest, const char *src)
Copy string.
Definition string.c:347
static void free_tls_session(struct refcnt *refcnt)
Free TLS session.
Definition tls.c:360
static struct x509_root * x509_root_get(struct x509_root *root)
Get reference to X.509 root certificate list.
Definition x509.h:393

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

◆ add_tls()

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

Add TLS on an interface.

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

Definition at line 3997 of file tls.c.

3998 {
3999 struct tls_connection *tls;
4000 int rc;
4001
4002 /* Allocate and initialise TLS structure */
4003 tls = malloc ( sizeof ( *tls ) );
4004 if ( ! tls ) {
4005 rc = -ENOMEM;
4006 goto err_alloc;
4007 }
4008 memset ( tls, 0, sizeof ( *tls ) );
4009 ref_init ( &tls->refcnt, free_tls );
4010 INIT_LIST_HEAD ( &tls->list );
4015 &tls->refcnt );
4016 tls->client.key = privkey_get ( key ? key : &private_key );
4018 tls->version = TLS_VERSION_MAX;
4019 tls_clear_cipher ( tls, &tls->tx.cipherspec.active );
4020 tls_clear_cipher ( tls, &tls->tx.cipherspec.pending );
4021 tls_clear_cipher ( tls, &tls->rx.cipherspec.active );
4022 tls_clear_cipher ( tls, &tls->rx.cipherspec.pending );
4023 tls_clear_handshake ( tls );
4024 iob_populate ( &tls->rx.iobuf, &tls->rx.header, 0,
4025 sizeof ( tls->rx.header ) );
4026 INIT_LIST_HEAD ( &tls->rx.data );
4027 if ( ( rc = tls_generate_random ( tls, &tls->client.random.random,
4028 ( sizeof ( tls->client.random.random ) ) ) ) != 0 ) {
4029 goto err_random;
4030 }
4031 if ( ( rc = tls_session ( tls, name ) ) != 0 )
4032 goto err_session;
4033 list_add_tail ( &tls->list, &tls->session->conn );
4034
4035 /* Start negotiation */
4036 tls_restart ( tls );
4037
4038 /* Attach to parent interface, mortalise self, and return */
4039 intf_insert ( xfer, &tls->plainstream, &tls->cipherstream );
4040 ref_put ( &tls->refcnt );
4041 return 0;
4042
4043 err_session:
4044 err_random:
4045 ref_put ( &tls->refcnt );
4046 err_alloc:
4047 return rc;
4048}
void intf_insert(struct interface *intf, struct interface *upper, struct interface *lower)
Insert a filter interface.
Definition interface.c:402
static void intf_init(struct interface *intf, struct interface_descriptor *desc, struct refcnt *refcnt)
Initialise an object interface.
Definition interface.h:204
static void iob_populate(struct io_buffer *iobuf, void *data, size_t len, size_t max_len)
Create a temporary I/O buffer.
Definition iobuf.h:195
static void process_init_stopped(struct process *process, struct process_descriptor *desc, struct refcnt *refcnt)
Initialise process without adding to process list.
Definition process.h:146
struct x509_root root_certificates
Root certificates.
Definition rootcert.c:79
struct stp_switch root
Root switch.
Definition stp.h:15
A private key.
Definition privkey.h:17
struct refcnt refcnt
Reference counter.
Definition tls.h:439
static struct interface_descriptor tls_cipherstream_desc
TLS ciphertext stream interface descriptor.
Definition tls.c:3721
static struct interface_descriptor tls_validator_desc
TLS certificate validator interface descriptor.
Definition tls.c:3795
static struct interface_descriptor tls_plainstream_desc
TLS plaintext stream interface descriptor.
Definition tls.c:3506
static void free_tls(struct refcnt *refcnt)
Free TLS connection.
Definition tls.c:384
static struct process_descriptor tls_process_desc
TLS TX process descriptor.
Definition tls.c:3920

References tls_cipherspec_pair::active, tls_rx::cipherspec, tls_tx::cipherspec, tls_connection::cipherstream, tls_connection::client, tls_session::conn, tls_rx::data, ENOMEM, free_tls(), tls_rx::header, INIT_LIST_HEAD, intf_init(), intf_insert(), iob_populate(), tls_rx::iobuf, key, tls_client::key, tls_connection::list, list_add_tail, malloc(), memset(), name, tls_cipherspec_pair::pending, tls_connection::plainstream, privkey_get(), tls_tx::process, process_init_stopped(), tls_client::random, tls_client_random::random, rc, ref_init, ref_put, tls_connection::refcnt, root, tls_server::root, root_certificates, tls_connection::rx, tls_connection::server, tls_connection::session, tls_cipherstream_desc, tls_clear_cipher(), tls_clear_handshake(), tls_generate_random(), tls_plainstream_desc, tls_process_desc, tls_restart(), tls_validator_desc, TLS_VERSION_MAX, tls_connection::tx, tls_server::validator, tls_connection::version, and x509_root_get().

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

◆ REQUIRING_SYMBOL()

REQUIRING_SYMBOL ( add_tls )

References add_tls().

◆ REQUIRE_OBJECT()

REQUIRE_OBJECT ( config_crypto )

Variable Documentation

◆ md5_sha1_algorithm

struct digest_algorithm md5_sha1_algorithm
static
Initial value:
= {
.name = "md5+sha1",
.ctxsize = sizeof ( struct md5_sha1_context ),
.blocksize = 0,
.digestsize = sizeof ( struct md5_sha1_digest ),
.init = md5_sha1_init,
.update = md5_sha1_update,
.final = md5_sha1_final,
}
static void md5_sha1_init(void *ctx)
Initialise MD5+SHA1 algorithm.
Definition tls.c:295
static void md5_sha1_final(void *ctx, void *out)
Generate MD5+SHA1 digest.
Definition tls.c:322
static void md5_sha1_update(void *ctx, const void *data, size_t len)
Accumulate data with MD5+SHA1 algorithm.
Definition tls.c:309

Hybrid MD5+SHA1 digest algorithm.

Definition at line 331 of file tls.c.

331 {
332 .name = "md5+sha1",
333 .ctxsize = sizeof ( struct md5_sha1_context ),
334 .blocksize = 0, /* Not applicable */
335 .digestsize = sizeof ( struct md5_sha1_digest ),
336 .init = md5_sha1_init,
337 .update = md5_sha1_update,
338 .final = md5_sha1_final,
339};

Referenced by tls_select_cipher(), and tls_verify_dh_params().

◆ __rsa_digestinfo_prefix

struct rsa_digestinfo_prefix rsa_md5_sha1_prefix __rsa_digestinfo_prefix
Initial value:
= {
.digest = &md5_sha1_algorithm,
.data = NULL,
.len = 0,
}

RSA digestInfo prefix for MD5+SHA1 algorithm.

Definition at line 342 of file tls.c.

342 {
343 .digest = &md5_sha1_algorithm,
344 .data = NULL, /* MD5+SHA1 signatures have no digestInfo */
345 .len = 0,
346};

◆ tls_cipher_suite_null

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

Null cipher suite.

Definition at line 855 of file tls.c.

855 {
857 .pubkey = &pubkey_null,
858 .cipher = &cipher_null,
859 .digest = &digest_null,
860};

Referenced by tls_change_cipher(), and tls_clear_cipher().

◆ tls_pubkey_exchange_algorithm

struct tls_key_exchange_algorithm tls_pubkey_exchange_algorithm
Initial value:
= {
.name = "pubkey",
}
static int tls_send_client_key_exchange_pubkey(struct tls_connection *tls)
Transmit Client Key Exchange record using public key exchange.
Definition tls.c:1421

Public key exchange algorithm.

Definition at line 1490 of file tls.c.

1490 {
1491 .name = "pubkey",
1493};

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

◆ tls_dhe_exchange_algorithm

struct tls_key_exchange_algorithm tls_dhe_exchange_algorithm
Initial value:
= {
.name = "dhe",
}
static int tls_send_client_key_exchange_dhe(struct tls_connection *tls)
Transmit Client Key Exchange record using DHE key exchange.
Definition tls.c:1591

Ephemeral Diffie-Hellman key exchange algorithm.

Definition at line 1705 of file tls.c.

1705 {
1706 .name = "dhe",
1708};

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

◆ tls_ecdhe_exchange_algorithm

struct tls_key_exchange_algorithm tls_ecdhe_exchange_algorithm
Initial value:
= {
.name = "ecdhe",
}
static int tls_send_client_key_exchange_ecdhe(struct tls_connection *tls)
Transmit Client Key Exchange record using ECDHE key exchange.
Definition tls.c:1716

Ephemeral Elliptic Curve Diffie-Hellman key exchange algorithm.

Definition at line 1835 of file tls.c.

1835 {
1836 .name = "ecdhe",
1838};

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

◆ tls_plainstream_ops

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

TLS plaintext stream interface descriptor.

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

TLS ciphertext stream interface operations.

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

TLS ciphertext stream interface descriptor.

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

TLS certificate validator interface operations.

Definition at line 3790 of file tls.c.

3790 {
3792};

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

TLS certificate validator interface descriptor.

Definition at line 3795 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:3811
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 3920 of file tls.c.

Referenced by add_tls().