iPXE
tls.c File Reference

Transport Layer Security Protocol. More...

#include <stdint.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <time.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_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 59 of file tls.c.

Referenced by tls_new_change_cipher().

◆ EINFO_EINVAL_CHANGE_CIPHER

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

Definition at line 60 of file tls.c.

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

◆ EINVAL_ALERT

#define EINVAL_ALERT   __einfo_error ( EINFO_EINVAL_ALERT )

Definition at line 63 of file tls.c.

Referenced by tls_new_alert().

◆ EINFO_EINVAL_ALERT

#define EINFO_EINVAL_ALERT
Value:
"Invalid Alert record" )

Definition at line 64 of file tls.c.

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

◆ EINVAL_HELLO

#define EINVAL_HELLO   __einfo_error ( EINFO_EINVAL_HELLO )

Definition at line 67 of file tls.c.

Referenced by tls_new_server_hello().

◆ EINFO_EINVAL_HELLO

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

Definition at line 68 of file tls.c.

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

◆ EINVAL_CERTIFICATE

#define EINVAL_CERTIFICATE   __einfo_error ( EINFO_EINVAL_CERTIFICATE )

Definition at line 71 of file tls.c.

Referenced by tls_parse_chain().

◆ EINFO_EINVAL_CERTIFICATE

#define EINFO_EINVAL_CERTIFICATE
Value:
"Invalid Certificate" )

Definition at line 72 of file tls.c.

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

◆ EINVAL_CERTIFICATES

#define EINVAL_CERTIFICATES   __einfo_error ( EINFO_EINVAL_CERTIFICATES )

Definition at line 75 of file tls.c.

Referenced by tls_new_certificate().

◆ EINFO_EINVAL_CERTIFICATES

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

Definition at line 76 of file tls.c.

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

◆ EINVAL_HELLO_DONE

#define EINVAL_HELLO_DONE   __einfo_error ( EINFO_EINVAL_HELLO_DONE )

Definition at line 79 of file tls.c.

Referenced by tls_new_server_hello_done().

◆ EINFO_EINVAL_HELLO_DONE

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

Definition at line 80 of file tls.c.

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

◆ EINVAL_FINISHED

#define EINVAL_FINISHED   __einfo_error ( EINFO_EINVAL_FINISHED )

Definition at line 83 of file tls.c.

Referenced by tls_new_finished().

◆ EINFO_EINVAL_FINISHED

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

Definition at line 84 of file tls.c.

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

◆ EINVAL_HANDSHAKE

#define EINVAL_HANDSHAKE   __einfo_error ( EINFO_EINVAL_HANDSHAKE )

Definition at line 87 of file tls.c.

◆ EINFO_EINVAL_HANDSHAKE

#define EINFO_EINVAL_HANDSHAKE
Value:
"Invalid Handshake record" )

Definition at line 88 of file tls.c.

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

◆ EINVAL_IV

#define EINVAL_IV   __einfo_error ( EINFO_EINVAL_IV )

Definition at line 91 of file tls.c.

Referenced by tls_new_ciphertext().

◆ EINFO_EINVAL_IV

#define EINFO_EINVAL_IV
Value:
"Invalid initialisation vector" )

Definition at line 92 of file tls.c.

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

◆ EINVAL_PADDING

#define EINVAL_PADDING   __einfo_error ( EINFO_EINVAL_PADDING )

Definition at line 95 of file tls.c.

Referenced by tls_verify_padding().

◆ EINFO_EINVAL_PADDING

#define EINFO_EINVAL_PADDING
Value:
"Invalid block padding" )

Definition at line 96 of file tls.c.

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

◆ EINVAL_RX_STATE

#define EINVAL_RX_STATE   __einfo_error ( EINFO_EINVAL_RX_STATE )

Definition at line 99 of file tls.c.

Referenced by tls_cipherstream_deliver().

◆ EINFO_EINVAL_RX_STATE

#define EINFO_EINVAL_RX_STATE
Value:
"Invalid receive state" )

Definition at line 100 of file tls.c.

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

◆ EINVAL_MAC

#define EINVAL_MAC   __einfo_error ( EINFO_EINVAL_MAC )

Definition at line 103 of file tls.c.

Referenced by tls_new_ciphertext().

◆ EINFO_EINVAL_MAC

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

Definition at line 104 of file tls.c.

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

◆ EINVAL_TICKET

#define EINVAL_TICKET   __einfo_error ( EINFO_EINVAL_TICKET )

Definition at line 107 of file tls.c.

Referenced by tls_new_session_ticket().

◆ EINFO_EINVAL_TICKET

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

Definition at line 108 of file tls.c.

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

◆ EINVAL_KEY_EXCHANGE

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

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

◆ EIO_ALERT

#define EIO_ALERT   __einfo_error ( EINFO_EIO_ALERT )

Definition at line 115 of file tls.c.

Referenced by tls_new_alert().

◆ EINFO_EIO_ALERT

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

Definition at line 116 of file tls.c.

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

◆ ENOMEM_CONTEXT

#define ENOMEM_CONTEXT   __einfo_error ( EINFO_ENOMEM_CONTEXT )

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

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

◆ ENOMEM_CERTIFICATE

#define ENOMEM_CERTIFICATE   __einfo_error ( EINFO_ENOMEM_CERTIFICATE )

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

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

◆ ENOMEM_CHAIN

#define ENOMEM_CHAIN   __einfo_error ( EINFO_ENOMEM_CHAIN )

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

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

◆ ENOMEM_TX_PLAINTEXT

#define ENOMEM_TX_PLAINTEXT   __einfo_error ( EINFO_ENOMEM_TX_PLAINTEXT )

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

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

◆ ENOMEM_TX_CIPHERTEXT

#define ENOMEM_TX_CIPHERTEXT   __einfo_error ( EINFO_ENOMEM_TX_CIPHERTEXT )

Definition at line 135 of file tls.c.

◆ EINFO_ENOMEM_TX_CIPHERTEXT

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

Definition at line 136 of file tls.c.

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

◆ ENOMEM_RX_DATA

#define ENOMEM_RX_DATA   __einfo_error ( EINFO_ENOMEM_RX_DATA )

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

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

◆ ENOMEM_RX_CONCAT

#define ENOMEM_RX_CONCAT   __einfo_error ( EINFO_ENOMEM_RX_CONCAT )

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

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

◆ ENOTSUP_CIPHER

#define ENOTSUP_CIPHER   __einfo_error ( EINFO_ENOTSUP_CIPHER )

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

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

◆ ENOTSUP_NULL

#define ENOTSUP_NULL   __einfo_error ( EINFO_ENOTSUP_NULL )

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

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

◆ ENOTSUP_SIG_HASH

#define ENOTSUP_SIG_HASH   __einfo_error ( EINFO_ENOTSUP_SIG_HASH )

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

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

◆ ENOTSUP_VERSION

#define ENOTSUP_VERSION   __einfo_error ( EINFO_ENOTSUP_VERSION )

Definition at line 159 of file tls.c.

◆ EINFO_ENOTSUP_VERSION

#define EINFO_ENOTSUP_VERSION
Value:
"Unsupported protocol version" )

Definition at line 160 of file tls.c.

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

◆ ENOTSUP_CURVE

#define ENOTSUP_CURVE   __einfo_error ( EINFO_ENOTSUP_CURVE )

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

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

◆ EPERM_ALERT

#define EPERM_ALERT   __einfo_error ( EINFO_EPERM_ALERT )

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

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

◆ EPERM_VERIFY

#define EPERM_VERIFY   __einfo_error ( EINFO_EPERM_VERIFY )

Definition at line 171 of file tls.c.

Referenced by tls_new_finished().

◆ EINFO_EPERM_VERIFY

#define EINFO_EPERM_VERIFY
Value:
"Handshake verification failed" )

Definition at line 172 of file tls.c.

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

◆ EPERM_RENEG_INSECURE

#define EPERM_RENEG_INSECURE   __einfo_error ( EINFO_EPERM_RENEG_INSECURE )

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

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

◆ EPERM_RENEG_VERIFY

#define EPERM_RENEG_VERIFY   __einfo_error ( EINFO_EPERM_RENEG_VERIFY )

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

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

◆ EPERM_KEY_EXCHANGE

#define EPERM_KEY_EXCHANGE   __einfo_error ( EINFO_EPERM_KEY_EXCHANGE )

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

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

◆ EPERM_EMS

#define EPERM_EMS   __einfo_error ( EINFO_EPERM_EMS )

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

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

◆ EPROTO_VERSION

#define EPROTO_VERSION   __einfo_error ( EINFO_EPROTO_VERSION )

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

192#define EINFO_EPROTO_VERSION \
193 __einfo_uniqify ( EINFO_EPROTO, 0x01, \
194 "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:567

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

623#define tls_prf_label( tls, secret, secret_len, out, out_len, label, ... ) \
624 tls_prf ( (tls), (secret), (secret_len), (out), (out_len), \
625 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 859 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 1005 of file tls.c.

1005#define TLS_NUM_SIG_HASH_ALGORITHMS \
1006 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 1077 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 1119 of file tls.c.

1119 {
1120 struct tls_connection *tls;
1121
1123 tls_tx_resume ( tls );
1124}
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition list.h:432
A TLS connection.
Definition tls.h:436
struct tls_session * session
Session.
Definition tls.h:441
struct list_head list
List of connections within the same session.
Definition tls.h:443
struct list_head conn
List of connections.
Definition tls.h:368
static void tls_tx_resume(struct tls_connection *tls)
Resume TX state machine.
Definition tls.c:1110

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

3027 {
3028 struct io_buffer *iobuf;
3029 size_t reserve;
3030
3031 /* Calculate maximum additional length to reserve */
3032 reserve = tls_iob_reserved ( tls, len );
3033
3034 /* Allocate I/O buffer */
3035 iobuf = xfer_alloc_iob ( &tls->cipherstream, ( reserve + len ) );
3036 if ( ! iobuf )
3037 return NULL;
3038
3039 /* Reserve space */
3040 iob_reserve ( iobuf, reserve );
3041
3042 return iobuf;
3043}
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:456
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:2999
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_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 3053 of file tls.c.

3054 {
3055 struct tls_cipherspec *cipherspec = &tls->tx.cipherspec.active;
3056 struct tls_cipher_suite *suite = cipherspec->suite;
3057 struct cipher_algorithm *cipher = suite->cipher;
3058 struct digest_algorithm *digest = suite->digest;
3059 struct {
3060 uint8_t fixed[suite->fixed_iv_len];
3061 uint8_t rec[suite->record_iv_len];
3062 } __attribute__ (( packed )) iv;
3063 struct tls_auth_header authhdr;
3064 struct tls_header *tlshdr;
3065 uint8_t mac[digest->digestsize];
3066 const void *plaintext;
3067 const void *encrypt;
3068 void *ciphertext;
3069 size_t record_len;
3070 size_t encrypt_len;
3071 size_t pad_len;
3072 size_t len;
3073 int rc;
3074
3075 /* Record plaintext pointer and length */
3076 plaintext = iobuf->data;
3077 len = iob_len ( iobuf );
3078
3079 /* Add to handshake digest if applicable */
3080 if ( type == TLS_TYPE_HANDSHAKE )
3081 tls_add_handshake ( tls, plaintext, len );
3082
3083 /* Start constructing ciphertext at start of reserved space */
3084 iob_push ( iobuf, tls_iob_reserved ( tls, len ) );
3085 iob_unput ( iobuf, iob_len ( iobuf ) );
3086
3087 /* Construct records */
3088 do {
3089 /* Limit length of this record (may be zero) */
3090 record_len = len;
3091 if ( record_len > TLS_TX_BUFSIZE )
3092 record_len = TLS_TX_BUFSIZE;
3093
3094 /* Construct and set initialisation vector */
3095 memcpy ( iv.fixed, cipherspec->fixed_iv, sizeof ( iv.fixed ) );
3096 if ( ( rc = tls_generate_random ( tls, iv.rec,
3097 sizeof ( iv.rec ) ) ) != 0 ) {
3098 goto err_random;
3099 }
3100 cipher_setiv ( cipher, cipherspec->cipher_ctx, &iv,
3101 sizeof ( iv ) );
3102
3103 /* Construct and process authentication data */
3104 authhdr.seq = cpu_to_be64 ( tls->tx.seq );
3105 authhdr.header.type = type;
3106 authhdr.header.version = htons ( tls->version );
3107 authhdr.header.length = htons ( record_len );
3108 if ( suite->mac_len ) {
3109 tls_hmac ( cipherspec, &authhdr, plaintext, record_len,
3110 mac );
3111 }
3112 if ( is_auth_cipher ( cipher ) ) {
3113 cipher_encrypt ( cipher, cipherspec->cipher_ctx,
3114 &authhdr, NULL, sizeof ( authhdr ) );
3115 }
3116
3117 /* Calculate encryption length */
3118 encrypt_len = ( record_len + suite->mac_len );
3119 if ( is_block_cipher ( cipher ) ) {
3120 pad_len = ( ( ( cipher->blocksize - 1 ) &
3121 -( encrypt_len + 1 ) ) + 1 );
3122 } else {
3123 pad_len = 0;
3124 }
3125 encrypt_len += pad_len;
3126
3127 /* Add record header */
3128 tlshdr = iob_put ( iobuf, sizeof ( *tlshdr ) );
3129 tlshdr->type = type;
3130 tlshdr->version = htons ( tls->version );
3131 tlshdr->length = htons ( sizeof ( iv.rec ) + encrypt_len +
3132 cipher->authsize );
3133
3134 /* Add record initialisation vector, if applicable */
3135 memcpy ( iob_put ( iobuf, sizeof ( iv.rec ) ), iv.rec,
3136 sizeof ( iv.rec ) );
3137
3138 /* Copy plaintext data if necessary */
3139 ciphertext = iob_put ( iobuf, record_len );
3140 assert ( ciphertext <= plaintext );
3141 if ( encrypt_len > record_len ) {
3142 memmove ( ciphertext, plaintext, record_len );
3143 encrypt = ciphertext;
3144 } else {
3145 encrypt = plaintext;
3146 }
3147
3148 /* Add MAC, if applicable */
3149 memcpy ( iob_put ( iobuf, suite->mac_len ), mac,
3150 suite->mac_len );
3151
3152 /* Add padding, if applicable */
3153 memset ( iob_put ( iobuf, pad_len ), ( pad_len - 1 ), pad_len );
3154
3155 /* Encrypt data and append authentication tag */
3156 DBGC2 ( tls, "Sending plaintext data:\n" );
3157 DBGC2_HDA ( tls, 0, encrypt, encrypt_len );
3158 cipher_encrypt ( cipher, cipherspec->cipher_ctx, encrypt,
3159 ciphertext, encrypt_len );
3160 cipher_auth ( cipher, cipherspec->cipher_ctx,
3161 iob_put ( iobuf, cipher->authsize ) );
3162
3163 /* Move to next record */
3164 tls->tx.seq += 1;
3165 plaintext += record_len;
3166 len -= record_len;
3167
3168 } while ( len );
3169
3170 /* Send ciphertext */
3171 if ( ( rc = xfer_deliver_iob ( &tls->cipherstream,
3172 iob_disown ( iobuf ) ) ) != 0 ) {
3173 DBGC ( tls, "TLS %p could not deliver ciphertext: %s\n",
3174 tls, strerror ( rc ) );
3175 goto err_deliver;
3176 }
3177
3178 assert ( iobuf == NULL );
3179 return 0;
3180
3181 err_deliver:
3182 err_random:
3183 free_iob ( iobuf );
3184 return rc;
3185}
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
unsigned char uint8_t
Definition stdint.h:10
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
#define __attribute__(x)
Definition compiler.h:10
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:155
A TLS cipher suite.
Definition tls.h:200
uint8_t fixed_iv_len
Fixed initialisation vector length.
Definition tls.h:216
struct cipher_algorithm * cipher
Bulk encryption cipher algorithm.
Definition tls.h:206
uint8_t mac_len
MAC length.
Definition tls.h:220
uint8_t record_iv_len
Record initialisation vector length.
Definition tls.h:218
struct digest_algorithm * digest
MAC digest algorithm.
Definition tls.h:208
struct tls_cipherspec active
Current cipher specification.
Definition tls.h:274
A TLS cipher specification.
Definition tls.h:258
void * fixed_iv
Fixed initialisation vector.
Definition tls.h:268
struct tls_cipher_suite * suite
Cipher suite.
Definition tls.h:260
void * cipher_ctx
Bulk encryption cipher context.
Definition tls.h:264
struct tls_tx tx
Transmit state.
Definition tls.h:474
uint16_t version
Protocol version.
Definition tls.h:459
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:376
struct tls_cipherspec_pair cipherspec
Cipher specifications.
Definition tls.h:374
static int tls_generate_random(struct tls_connection *tls, void *data, size_t len)
Generate random data.
Definition tls.c:460
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:2958
static int tls_add_handshake(struct tls_connection *tls, const void *data, size_t len)
Add handshake record to verification hash.
Definition tls.c:819
#define TLS_TX_BUFSIZE
TX maximum fragment length.
Definition tls.h:492
#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 3196 of file tls.c.

3197 {
3198 struct io_buffer *iobuf;
3199 int rc;
3200
3201 /* Allocate I/O buffer */
3202 iobuf = tls_alloc_iob ( tls, len );
3203 if ( ! iobuf )
3204 return -ENOMEM_TX_PLAINTEXT;
3205 memcpy ( iob_put ( iobuf, len ), data, len );
3206
3207 /* Transmit I/O buffer */
3208 if ( ( rc = tls_send_record ( tls, type, iob_disown ( iobuf ) ) ) != 0 )
3209 return rc;
3210
3211 return 0;
3212}
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:3026
static int tls_send_record(struct tls_connection *tls, unsigned int type, struct io_buffer *iobuf)
Send plaintext record(s)
Definition tls.c:3053
#define ENOMEM_TX_PLAINTEXT
Definition tls.c:131

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

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

835 {
836 struct digest_algorithm *digest = tls->handshake_digest;
837 uint8_t ctx[ digest->ctxsize ];
838
839 memcpy ( ctx, tls->handshake_ctx, sizeof ( ctx ) );
840 digest_final ( digest, ctx, out );
841}
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:465
struct digest_algorithm * handshake_digest
Digest algorithm used for handshake verification.
Definition tls.h:463

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

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

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

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

260 {
261 return ( ( ! is_pending ( &tls->client.negotiation ) ) &&
262 ( ! is_pending ( &tls->server.negotiation ) ) );
263}
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:410
struct tls_server server
Server state.
Definition tls.h:480
struct tls_client client
Client state.
Definition tls.h:478
struct pending_operation negotiation
Security negotiation pending operation.
Definition tls.h:432

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

277 {
278 return ( ( TLS_VERSION_MIN >= version ) ||
279 ( tls->version >= version ) );
280}
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 294 of file tls.c.

294 {
295 struct md5_sha1_context *context = ctx;
296
297 digest_init ( &md5_algorithm, context->md5 );
298 digest_init ( &sha1_algorithm, context->sha1 );
299}
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:319
uint8_t sha1[SHA1_CTX_SIZE]
SHA-1 context.
Definition tls.h:323
uint8_t md5[MD5_CTX_SIZE]
MD5 context.
Definition tls.h:321

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

308 {
309 struct md5_sha1_context *context = ctx;
310
311 digest_update ( &md5_algorithm, context->md5, data, len );
312 digest_update ( &sha1_algorithm, context->sha1, data, len );
313}
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 321 of file tls.c.

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

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

359 {
360 struct tls_session *session =
362
363 /* Sanity check */
364 assert ( list_empty ( &session->conn ) );
365
366 /* Remove from list of sessions */
367 list_del ( &session->list );
368
369 /* Free dynamically-allocated resources */
370 x509_root_put ( session->root );
371 privkey_put ( session->key );
372 free ( session->ticket );
373
374 /* Free session */
375 free ( session );
376}
#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:341
struct private_key * key
Private key.
Definition tls.h:352
struct x509_root * root
Root of trust.
Definition tls.h:350
void * ticket
Session ticket.
Definition tls.h:359
struct list_head list
List of sessions.
Definition tls.h:345
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 383 of file tls.c.

383 {
384 struct tls_connection *tls =
386 struct tls_session *session = tls->session;
387 struct io_buffer *iobuf;
388 struct io_buffer *tmp;
389
390 /* Free dynamically-allocated resources */
391 free ( tls->new_session_ticket );
392 tls_clear_cipher ( tls, &tls->tx.cipherspec.active );
393 tls_clear_cipher ( tls, &tls->tx.cipherspec.pending );
394 tls_clear_cipher ( tls, &tls->rx.cipherspec.active );
395 tls_clear_cipher ( tls, &tls->rx.cipherspec.pending );
396 free ( tls->server.exchange );
397 free ( tls->handshake_ctx );
398 list_for_each_entry_safe ( iobuf, tmp, &tls->rx.data, list ) {
399 list_del ( &iobuf->list );
400 free_iob ( iobuf );
401 }
402 free_iob ( tls->rx.handshake );
403 privkey_put ( tls->client.key );
404 x509_chain_put ( tls->client.chain );
405 x509_chain_put ( tls->server.chain );
406 x509_root_put ( tls->server.root );
407
408 /* Drop reference to session */
409 assert ( list_empty ( &tls->list ) );
410 ref_put ( &session->refcnt );
411
412 /* Free TLS structure itself */
413 free ( tls );
414}
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:276
struct private_key * key
Private key (if used)
Definition tls.h:406
struct x509_chain * chain
Certificate chain (if used)
Definition tls.h:408
struct tls_rx rx
Receive state.
Definition tls.h:476
void * new_session_ticket
New session ticket.
Definition tls.h:449
struct tls_cipherspec_pair cipherspec
Cipher specifications.
Definition tls.h:386
struct list_head data
List of received data buffers.
Definition tls.h:396
struct io_buffer * handshake
Received handshake fragment.
Definition tls.h:398
struct x509_root * root
Root of trust.
Definition tls.h:422
void * exchange
Server Key Exchange record (if any)
Definition tls.h:418
struct x509_chain * chain
Certificate chain.
Definition tls.h:424
struct refcnt refcnt
Reference counter.
Definition tls.h:343
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 422 of file tls.c.

422 {
423
424 /* Remove pending operations, if applicable */
427 pending_put ( &tls->server.validation );
428
429 /* Remove process */
430 process_del ( &tls->tx.process );
431
432 /* Close all interfaces */
433 intf_shutdown ( &tls->cipherstream, rc );
434 intf_shutdown ( &tls->plainstream, rc );
435 intf_shutdown ( &tls->server.validator, rc );
436
437 /* Remove from session */
438 list_del ( &tls->list );
439 INIT_LIST_HEAD ( &tls->list );
440
441 /* Resume all other connections, in case we were the lead connection */
442 tls_tx_resume_all ( tls->session );
443}
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:454
struct pending_operation validation
Certificate validation pending operation.
Definition tls.h:430
struct interface validator
Certificate validator.
Definition tls.h:428
struct process process
Transmit process.
Definition tls.h:380
static void tls_tx_resume_all(struct tls_session *session)
Resume TX state machine for all connections within a session.
Definition tls.c:1119

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_tx_resume_all(), tls_connection::tx, tls_server::validation, and tls_server::validator.

Referenced by tls_cipherstream_deliver(), 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 460 of file tls.c.

461 {
462 int rc;
463
464 /* Generate random bits with no additional input and without
465 * prediction resistance
466 */
467 if ( ( rc = rbg_generate ( NULL, 0, 0, data, len ) ) != 0 ) {
468 DBGC ( tls, "TLS %p could not generate random data: %s\n",
469 tls, strerror ( rc ) );
470 return rc;
471 }
472
473 return 0;
474}
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 483 of file tls.c.

484 {
485 void *data;
486 size_t len;
487
488 while ( ( data = va_arg ( args, void * ) ) ) {
489 len = va_arg ( args, size_t );
490 hmac_update ( digest, ctx, data, len );
491 }
492}
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 505 of file tls.c.

509 {
510 uint8_t ctx[ hmac_ctxsize ( digest ) ];
511 uint8_t ctx_partial[ sizeof ( ctx ) ];
512 uint8_t a[digest->digestsize];
513 uint8_t out_tmp[digest->digestsize];
514 size_t frag_len = digest->digestsize;
515 va_list tmp;
516
517 DBGC2 ( tls, "TLS %p %s secret:\n", tls, digest->name );
518 DBGC2_HD ( tls, secret, secret_len );
519
520 /* Calculate A(1) */
521 hmac_init ( digest, ctx, secret, secret_len );
522 va_copy ( tmp, seeds );
523 tls_hmac_update_va ( digest, ctx, tmp );
524 va_end ( tmp );
525 hmac_final ( digest, ctx, a );
526 DBGC2 ( tls, "TLS %p %s A(1):\n", tls, digest->name );
527 DBGC2_HD ( tls, &a, sizeof ( a ) );
528
529 /* Generate as much data as required */
530 while ( out_len ) {
531 /* Calculate output portion */
532 hmac_init ( digest, ctx, secret, secret_len );
533 hmac_update ( digest, ctx, a, sizeof ( a ) );
534 memcpy ( ctx_partial, ctx, sizeof ( ctx_partial ) );
535 va_copy ( tmp, seeds );
536 tls_hmac_update_va ( digest, ctx, tmp );
537 va_end ( tmp );
538 hmac_final ( digest, ctx, out_tmp );
539
540 /* Copy output */
541 if ( frag_len > out_len )
542 frag_len = out_len;
543 memcpy ( out, out_tmp, frag_len );
544 DBGC2 ( tls, "TLS %p %s output:\n", tls, digest->name );
545 DBGC2_HD ( tls, out, frag_len );
546
547 /* Calculate A(i) */
548 hmac_final ( digest, ctx_partial, a );
549 DBGC2 ( tls, "TLS %p %s A(n):\n", tls, digest->name );
550 DBGC2_HD ( tls, &a, sizeof ( a ) );
551
552 out += frag_len;
553 out_len -= frag_len;
554 }
555}
#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:483

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

568 {
569 va_list seeds;
570 va_list tmp;
571 size_t subsecret_len;
572 const void *md5_secret;
573 const void *sha1_secret;
574 uint8_t buf[out_len];
575 unsigned int i;
576
577 va_start ( seeds, out_len );
578
579 if ( tls_version ( tls, TLS_VERSION_TLS_1_2 ) ) {
580 /* Use handshake digest PRF for TLSv1.2 and later */
581 tls_p_hash_va ( tls, tls->handshake_digest, secret, secret_len,
582 out, out_len, seeds );
583 } else {
584 /* Use combination of P_MD5 and P_SHA-1 for TLSv1.1
585 * and earlier
586 */
587
588 /* Split secret into two, with an overlap of up to one byte */
589 subsecret_len = ( ( secret_len + 1 ) / 2 );
590 md5_secret = secret;
591 sha1_secret = ( secret + secret_len - subsecret_len );
592
593 /* Calculate MD5 portion */
594 va_copy ( tmp, seeds );
595 tls_p_hash_va ( tls, &md5_algorithm, md5_secret,
596 subsecret_len, out, out_len, seeds );
597 va_end ( tmp );
598
599 /* Calculate SHA1 portion */
600 va_copy ( tmp, seeds );
601 tls_p_hash_va ( tls, &sha1_algorithm, sha1_secret,
602 subsecret_len, buf, out_len, seeds );
603 va_end ( tmp );
604
605 /* XOR the two portions together into the final output buffer */
606 for ( i = 0 ; i < out_len ; i++ )
607 *( ( uint8_t * ) out + i ) ^= buf[i];
608 }
609
610 va_end ( seeds );
611}
#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:505
static int tls_version(struct tls_connection *tls, unsigned int version)
Check for TLS version.
Definition tls.c:277
#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 643 of file tls.c.

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

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

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

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

778 {
779
780 /* Select null digest algorithm */
782
783 /* Free any existing context */
784 free ( tls->handshake_ctx );
785 tls->handshake_ctx = NULL;
786}
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 795 of file tls.c.

796 {
797
798 /* Clear existing handshake digest */
799 tls_clear_handshake ( tls );
800
801 /* Allocate and initialise context */
802 tls->handshake_ctx = malloc ( digest->ctxsize );
803 if ( ! tls->handshake_ctx )
804 return -ENOMEM;
805 tls->handshake_digest = digest;
806 digest_init ( digest, tls->handshake_ctx );
807
808 return 0;
809}
#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:778

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

820 {
821 struct digest_algorithm *digest = tls->handshake_digest;
822
823 digest_update ( digest, tls->handshake_ctx, data, len );
824 return 0;
825}

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

868 {
869 struct tls_cipher_suite *suite;
870
871 /* Identify cipher suite */
873 if ( suite->code == cipher_suite )
874 return suite;
875 }
876
877 return NULL;
878}
uint16_t code
Numeric code (in network-endian order)
Definition tls.h:212
#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:224

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

886 {
887
888 free ( cipherspec->dynamic );
889 memset ( cipherspec, 0, sizeof ( *cipherspec ) );
890 cipherspec->suite = &tls_cipher_suite_null;
891}
void * dynamic
Dynamically-allocated storage.
Definition tls.h:262
struct tls_cipher_suite tls_cipher_suite_null
Null cipher suite.
Definition tls.c:851

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

903 {
904 struct cipher_algorithm *cipher = suite->cipher;
905 size_t total;
906 void *dynamic;
907
908 /* Clear out old cipher contents, if any */
909 tls_clear_cipher ( tls, cipherspec );
910
911 /* Allocate dynamic storage */
912 total = ( cipher->ctxsize + suite->mac_len + suite->fixed_iv_len );
913 dynamic = zalloc ( total );
914 if ( ! dynamic ) {
915 DBGC ( tls, "TLS %p could not allocate %zd bytes for crypto "
916 "context\n", tls, total );
917 return -ENOMEM_CONTEXT;
918 }
919
920 /* Assign storage */
921 cipherspec->dynamic = dynamic;
922 cipherspec->cipher_ctx = dynamic; dynamic += cipher->ctxsize;
923 cipherspec->mac_secret = dynamic; dynamic += suite->mac_len;
924 cipherspec->fixed_iv = dynamic; dynamic += suite->fixed_iv_len;
925 assert ( ( cipherspec->dynamic + total ) == dynamic );
926
927 /* Store parameters */
928 cipherspec->suite = suite;
929
930 return 0;
931}
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:119

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

941 {
942 struct tls_cipher_suite *suite;
943 struct digest_algorithm *digest;
944 int rc;
945
946 /* Identify cipher suite */
947 suite = tls_find_cipher_suite ( cipher_suite );
948 if ( ! suite ) {
949 DBGC ( tls, "TLS %p does not support cipher %04x\n",
950 tls, ntohs ( cipher_suite ) );
951 return -ENOTSUP_CIPHER;
952 }
953
954 /* Set handshake digest algorithm */
955 digest = ( tls_version ( tls, TLS_VERSION_TLS_1_2 ) ?
956 suite->handshake : &md5_sha1_algorithm );
957 if ( ( rc = tls_select_handshake ( tls, digest ) ) != 0 )
958 return rc;
959
960 /* Set ciphers */
961 if ( ( rc = tls_set_cipher ( tls, &tls->tx.cipherspec.pending,
962 suite ) ) != 0 )
963 return rc;
964 if ( ( rc = tls_set_cipher ( tls, &tls->rx.cipherspec.pending,
965 suite ) ) != 0 )
966 return rc;
967
968 DBGC ( tls, "TLS %p selected %s-%s-%s-%d-%s\n", tls,
969 suite->exchange->name, suite->pubkey->name,
970 suite->cipher->name, ( suite->key_len * 8 ),
971 suite->digest->name );
972
973 return 0;
974}
#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:204
struct tls_key_exchange_algorithm * exchange
Key exchange algorithm.
Definition tls.h:202
struct digest_algorithm * handshake
Handshake digest algorithm (for TLSv1.2 and above)
Definition tls.h:210
const char * name
Algorithm name.
Definition tls.h:189
#define ENOTSUP_CIPHER
Definition tls.c:147
static int tls_select_handshake(struct tls_connection *tls, struct digest_algorithm *digest)
Select handshake digest algorithm.
Definition tls.c:795
static int tls_set_cipher(struct tls_connection *tls, struct tls_cipherspec *cipherspec, struct tls_cipher_suite *suite)
Set cipher suite.
Definition tls.c:901
static struct tls_cipher_suite * tls_find_cipher_suite(unsigned int cipher_suite)
Identify cipher suite.
Definition tls.c:868
static struct digest_algorithm md5_sha1_algorithm
Hybrid MD5+SHA1 digest algorithm.
Definition tls.c:330

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

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

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

1017 {
1018 struct tls_signature_hash_algorithm *sig_hash;
1019
1020 /* Identify signature and hash algorithm */
1022 if ( ( sig_hash->pubkey == pubkey ) &&
1023 ( sig_hash->digest == digest ) ) {
1024 return sig_hash;
1025 }
1026 }
1027
1028 return NULL;
1029}
A TLS signature algorithm.
Definition tls.h:288
struct pubkey_algorithm * pubkey
Public-key algorithm.
Definition tls.h:292
struct digest_algorithm * digest
Digest algorithm.
Definition tls.h:290
#define TLS_SIG_HASH_ALGORITHMS
TLS signature hash algorithm table.
Definition tls.h:302

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

1038 {
1039 struct tls_signature_hash_algorithm *sig_hash;
1040
1041 /* Identify signature and hash algorithm */
1043 if ( sig_hash->code.signature == code.signature )
1044 return sig_hash->pubkey;
1045 }
1046
1047 return NULL;
1048}
static unsigned int code
Response code.
Definition hyperv.h:26
struct tls_signature_hash_id code
Numeric code.
Definition tls.h:294
uint8_t signature
Signature algorithm.
Definition tls.h:284

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

1057 {
1058 struct tls_signature_hash_algorithm *sig_hash;
1059
1060 /* Identify signature and hash algorithm */
1062 if ( sig_hash->code.hash == code.hash )
1063 return sig_hash->digest;
1064 }
1065
1066 return NULL;
1067}
uint8_t hash
Hash algorithm.
Definition tls.h:282

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

1086 {
1087 struct tls_named_curve *curve;
1088
1089 /* Identify named curve */
1091 if ( curve->code == named_curve )
1092 return curve;
1093 }
1094
1095 return NULL;
1096}
A TLS named curve.
Definition tls.h:238
struct elliptic_curve * curve
Elliptic curve.
Definition tls.h:240
#define TLS_NAMED_CURVES
TLS named curve table.
Definition tls.h:250

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

1110 {
1111 process_add ( &tls->tx.process );
1112}
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 1131 of file tls.c.

1131 {
1132
1133 /* Sanity check */
1134 assert ( ! tls->tx.pending );
1135 assert ( ! is_pending ( &tls->client.negotiation ) );
1136 assert ( ! is_pending ( &tls->server.negotiation ) );
1137 assert ( ! is_pending ( &tls->server.validation ) );
1138
1139 /* (Re)start negotiation */
1141 tls_tx_resume ( tls );
1142 pending_get ( &tls->client.negotiation );
1143 pending_get ( &tls->server.negotiation );
1144}
void pending_get(struct pending_operation *pending)
Mark an operation as pending.
Definition pending.c:46
unsigned int pending
Pending transmissions.
Definition tls.h:378
@ TLS_TX_CLIENT_HELLO
Definition tls.h:178

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

1155 {
1156
1157 /* Send record */
1159}
static int tls_send_plaintext(struct tls_connection *tls, unsigned int type, const void *data, size_t len)
Send plaintext record.
Definition tls.c:3196

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

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

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

1349 {
1350
1351 return tls_client_hello ( tls, tls_send_handshake );
1352}
static int tls_send_handshake(struct tls_connection *tls, const void *data, size_t len)
Transmit Handshake record.
Definition tls.c:1154
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:1168

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

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

1417 {
1418 struct tls_cipherspec *cipherspec = &tls->tx.cipherspec.pending;
1419 struct pubkey_algorithm *pubkey = cipherspec->suite->pubkey;
1420 struct {
1422 uint8_t random[46];
1423 } __attribute__ (( packed )) pre_master_secret;
1424 struct asn1_cursor cursor = {
1425 .data = &pre_master_secret,
1426 .len = sizeof ( pre_master_secret ),
1427 };
1428 struct asn1_builder builder = { NULL, 0 };
1429 int rc;
1430
1431 /* Generate pre-master secret */
1432 pre_master_secret.version = htons ( TLS_VERSION_MAX );
1433 if ( ( rc = tls_generate_random ( tls, &pre_master_secret.random,
1434 ( sizeof ( pre_master_secret.random ) ) ) ) != 0 ) {
1435 goto err_random;
1436 }
1437
1438 /* Encrypt pre-master secret using server's public key */
1439 if ( ( rc = pubkey_encrypt ( pubkey, &tls->server.key, &cursor,
1440 &builder ) ) != 0 ) {
1441 DBGC ( tls, "TLS %p could not encrypt pre-master secret: %s\n",
1442 tls, strerror ( rc ) );
1443 goto err_encrypt;
1444 }
1445
1446 /* Construct Client Key Exchange record */
1447 {
1448 struct {
1449 uint32_t type_length;
1450 uint16_t encrypted_pre_master_secret_len;
1451 } __attribute__ (( packed )) header;
1452
1453 header.type_length =
1455 htonl ( builder.len + sizeof ( header ) -
1456 sizeof ( header.type_length ) ) );
1457 header.encrypted_pre_master_secret_len = htons ( builder.len );
1458
1459 if ( ( rc = asn1_prepend_raw ( &builder, &header,
1460 sizeof ( header ) ) ) != 0 ) {
1461 DBGC ( tls, "TLS %p could not construct Client Key "
1462 "Exchange: %s\n", tls, strerror ( rc ) );
1463 goto err_prepend;
1464 }
1465 }
1466
1467 /* Transmit Client Key Exchange record */
1468 if ( ( rc = tls_send_handshake ( tls, builder.data,
1469 builder.len ) ) != 0 ) {
1470 goto err_send;
1471 }
1472
1473 /* Generate master secret */
1474 tls_generate_master_secret ( tls, &pre_master_secret,
1475 sizeof ( pre_master_secret ) );
1476
1477 err_random:
1478 err_encrypt:
1479 err_prepend:
1480 err_send:
1481 free ( builder.data );
1482 return rc;
1483}
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:426
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:643
#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 1498 of file tls.c.

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

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

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

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

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

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

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

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

1951 {
1952 static const struct {
1953 uint8_t spec;
1954 } __attribute__ (( packed )) change_cipher = {
1955 .spec = TLS_CHANGE_CIPHER_SPEC,
1956 };
1957
1959 &change_cipher, sizeof ( change_cipher ) );
1960}
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 1968 of file tls.c.

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

2010 {
2011 const struct {
2012 uint8_t spec;
2013 } __attribute__ (( packed )) *change_cipher = iobuf->data;
2014 size_t len = iob_len ( iobuf );
2015 int rc;
2016
2017 /* Sanity check */
2018 if ( ( sizeof ( *change_cipher ) != len ) ||
2019 ( change_cipher->spec != TLS_CHANGE_CIPHER_SPEC ) ) {
2020 DBGC ( tls, "TLS %p received invalid Change Cipher\n", tls );
2021 DBGC_HD ( tls, change_cipher, len );
2022 return -EINVAL_CHANGE_CIPHER;
2023 }
2024 iob_pull ( iobuf, sizeof ( *change_cipher ) );
2025
2026 /* Change receive cipher spec */
2027 if ( ( rc = tls_change_cipher ( tls, &tls->rx.cipherspec ) ) != 0 ) {
2028 DBGC ( tls, "TLS %p could not activate RX cipher: %s\n",
2029 tls, strerror ( rc ) );
2030 return rc;
2031 }
2032 tls->rx.seq = ~( ( uint64_t ) 0 );
2033
2034 return 0;
2035}
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:388
#define EINVAL_CHANGE_CIPHER
Definition tls.c:59
static int tls_change_cipher(struct tls_connection *tls, struct tls_cipherspec_pair *pair)
Activate next cipher suite.
Definition tls.c:983

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

2045 {
2046 const struct {
2047 uint8_t level;
2048 uint8_t description;
2049 char next[0];
2050 } __attribute__ (( packed )) *alert = iobuf->data;
2051 size_t len = iob_len ( iobuf );
2052
2053 /* Sanity check */
2054 if ( sizeof ( *alert ) != len ) {
2055 DBGC ( tls, "TLS %p received overlength Alert\n", tls );
2056 DBGC_HD ( tls, alert, len );
2057 return -EINVAL_ALERT;
2058 }
2059 iob_pull ( iobuf, sizeof ( *alert ) );
2060
2061 /* Handle alert */
2062 switch ( alert->level ) {
2063 case TLS_ALERT_WARNING:
2064 DBGC ( tls, "TLS %p received warning alert %d\n",
2065 tls, alert->description );
2066 return 0;
2067 case TLS_ALERT_FATAL:
2068 DBGC ( tls, "TLS %p received fatal alert %d\n",
2069 tls, alert->description );
2070 return -EPERM_ALERT;
2071 default:
2072 DBGC ( tls, "TLS %p received unknown alert level %d"
2073 "(alert %d)\n", tls, alert->level, alert->description );
2074 return -EIO_ALERT;
2075 }
2076}
uint32_t next
Next descriptor address.
Definition dwmac.h:11
void alert(unsigned int row, const char *fmt,...)
Show alert message.
Definition message.c:104
#define EINVAL_ALERT
Definition tls.c:63
#define EPERM_ALERT
Definition tls.c:167
#define EIO_ALERT
Definition tls.c:115
#define TLS_ALERT_FATAL
Definition tls.h:83
#define TLS_ALERT_WARNING
Definition tls.h:82

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

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

2088 {
2089
2090 /* Ignore if a handshake is in progress */
2091 if ( ! tls_ready ( tls ) ) {
2092 DBGC ( tls, "TLS %p ignoring Hello Request\n", tls );
2093 return 0;
2094 }
2095
2096 /* Fail unless server supports secure renegotiation */
2097 if ( ! ( tls->secure_renegotiation && tls->extended_master_secret ) ) {
2098 DBGC ( tls, "TLS %p refusing to renegotiate insecurely\n",
2099 tls );
2100 return -EPERM_RENEG_INSECURE;
2101 }
2102
2103 /* Restart negotiation */
2104 tls_restart ( tls );
2105
2106 return 0;
2107}
static int tls_ready(struct tls_connection *tls)
Determine if TLS connection is ready for application data.
Definition tls.c:260
static void tls_restart(struct tls_connection *tls)
Restart negotiation.
Definition tls.c:1131
#define EPERM_RENEG_INSECURE
Definition tls.c:175

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

2118 {
2119 const struct {
2121 uint8_t random[32];
2122 uint8_t session_id_len;
2123 uint8_t session_id[0];
2124 } __attribute__ (( packed )) *hello_a = data;
2125 const uint8_t *session_id;
2126 const struct {
2127 uint16_t cipher_suite;
2128 uint8_t compression_method;
2129 char next[0];
2130 } __attribute__ (( packed )) *hello_b;
2131 const struct {
2132 uint16_t len;
2133 uint8_t data[0];
2134 } __attribute__ (( packed )) *exts;
2135 const struct {
2136 uint16_t type;
2137 uint16_t len;
2138 uint8_t data[0];
2139 } __attribute__ (( packed )) *ext;
2140 const struct {
2141 uint8_t len;
2142 uint8_t data[0];
2143 } __attribute__ (( packed )) *reneg = NULL;
2144 const struct {
2145 uint8_t data[0];
2146 } __attribute__ (( packed )) *ems = NULL;
2148 size_t exts_len;
2149 size_t ext_len;
2150 size_t remaining;
2151 int rc;
2152
2153 /* Parse header */
2154 if ( ( sizeof ( *hello_a ) > len ) ||
2155 ( hello_a->session_id_len > ( len - sizeof ( *hello_a ) ) ) ||
2156 ( sizeof ( *hello_b ) > ( len - sizeof ( *hello_a ) -
2157 hello_a->session_id_len ) ) ) {
2158 DBGC ( tls, "TLS %p received underlength Server Hello\n", tls );
2159 DBGC_HD ( tls, data, len );
2160 return -EINVAL_HELLO;
2161 }
2162 session_id = hello_a->session_id;
2163 hello_b = ( ( void * ) ( session_id + hello_a->session_id_len ) );
2164
2165 /* Parse extensions, if present */
2166 remaining = ( len - sizeof ( *hello_a ) - hello_a->session_id_len -
2167 sizeof ( *hello_b ) );
2168 if ( remaining ) {
2169
2170 /* Parse extensions length */
2171 exts = ( ( void * ) hello_b->next );
2172 if ( ( sizeof ( *exts ) > remaining ) ||
2173 ( ( exts_len = ntohs ( exts->len ) ) >
2174 ( remaining - sizeof ( *exts ) ) ) ) {
2175 DBGC ( tls, "TLS %p received underlength extensions\n",
2176 tls );
2177 DBGC_HD ( tls, data, len );
2178 return -EINVAL_HELLO;
2179 }
2180
2181 /* Parse extensions */
2182 for ( ext = ( ( void * ) exts->data ), remaining = exts_len ;
2183 remaining ;
2184 ext = ( ( ( void * ) ext ) + sizeof ( *ext ) + ext_len ),
2185 remaining -= ( sizeof ( *ext ) + ext_len ) ) {
2186
2187 /* Parse extension length */
2188 if ( ( sizeof ( *ext ) > remaining ) ||
2189 ( ( ext_len = ntohs ( ext->len ) ) >
2190 ( remaining - sizeof ( *ext ) ) ) ) {
2191 DBGC ( tls, "TLS %p received underlength "
2192 "extension\n", tls );
2193 DBGC_HD ( tls, data, len );
2194 return -EINVAL_HELLO;
2195 }
2196
2197 /* Record known extensions */
2198 switch ( ext->type ) {
2199 case htons ( TLS_RENEGOTIATION_INFO ) :
2200 reneg = ( ( void * ) ext->data );
2201 if ( ( sizeof ( *reneg ) > ext_len ) ||
2202 ( reneg->len >
2203 ( ext_len - sizeof ( *reneg ) ) ) ) {
2204 DBGC ( tls, "TLS %p received "
2205 "underlength renegotiation "
2206 "info\n", tls );
2207 DBGC_HD ( tls, data, len );
2208 return -EINVAL_HELLO;
2209 }
2210 break;
2212 ems = ( ( void * ) ext->data );
2213 break;
2214 }
2215 }
2216 }
2217
2218 /* Check and store protocol version */
2219 version = ntohs ( hello_a->version );
2220 if ( version < TLS_VERSION_MIN ) {
2221 DBGC ( tls, "TLS %p does not support protocol version %d.%d\n",
2222 tls, ( version >> 8 ), ( version & 0xff ) );
2223 return -ENOTSUP_VERSION;
2224 }
2225 if ( version > tls->version ) {
2226 DBGC ( tls, "TLS %p server attempted to illegally upgrade to "
2227 "protocol version %d.%d\n",
2228 tls, ( version >> 8 ), ( version & 0xff ) );
2229 return -EPROTO_VERSION;
2230 }
2231 tls->version = version;
2232 DBGC ( tls, "TLS %p using protocol version %d.%d\n",
2233 tls, ( version >> 8 ), ( version & 0xff ) );
2234
2235 /* Select cipher suite */
2236 if ( ( rc = tls_select_cipher ( tls, hello_b->cipher_suite ) ) != 0 )
2237 return rc;
2238
2239 /* Add preceding Client Hello to handshake digest */
2240 if ( ( rc = tls_client_hello ( tls, tls_add_handshake ) ) != 0 )
2241 return rc;
2242
2243 /* Copy out server random bytes */
2244 memcpy ( &tls->server.random, &hello_a->random,
2245 sizeof ( tls->server.random ) );
2246
2247 /* Handle extended master secret */
2248 tls->extended_master_secret = ( !! ems );
2249
2250 /* Check session ID */
2251 if ( hello_a->session_id_len &&
2252 ( hello_a->session_id_len == tls->session_id_len ) &&
2253 ( memcmp ( session_id, tls->session_id,
2254 tls->session_id_len ) == 0 ) ) {
2255
2256 /* Session ID match: reuse master secret */
2257 DBGC ( tls, "TLS %p resuming session ID:\n", tls );
2258 DBGC_HDA ( tls, 0, tls->session_id, tls->session_id_len );
2259 if ( ( rc = tls_generate_keys ( tls ) ) != 0 )
2260 return rc;
2261
2262 /* Ensure master secret generation method matches */
2263 if ( tls->extended_master_secret !=
2265 DBGC ( tls, "TLS %p mismatched extended master secret "
2266 "extension\n", tls );
2267 return -EPERM_EMS;
2268 }
2269
2270 } else {
2271
2272 /* Record new session ID, if present */
2273 if ( hello_a->session_id_len &&
2274 ( hello_a->session_id_len <= sizeof ( tls->session_id ))){
2275 tls->session_id_len = hello_a->session_id_len;
2276 memcpy ( tls->session_id, session_id,
2277 tls->session_id_len );
2278 DBGC ( tls, "TLS %p new session ID:\n", tls );
2279 DBGC_HDA ( tls, 0, tls->session_id,
2280 tls->session_id_len );
2281 }
2282 }
2283
2284 /* Handle secure renegotiation */
2285 if ( tls->secure_renegotiation ) {
2286
2287 /* Secure renegotiation is expected; verify data */
2288 if ( ( reneg == NULL ) ||
2289 ( reneg->len != sizeof ( tls->verify ) ) ||
2290 ( memcmp ( reneg->data, &tls->verify,
2291 sizeof ( tls->verify ) ) != 0 ) ) {
2292 DBGC ( tls, "TLS %p server failed secure "
2293 "renegotiation\n", tls );
2294 return -EPERM_RENEG_VERIFY;
2295 }
2296
2297 } else if ( reneg != NULL ) {
2298
2299 /* Secure renegotiation is being enabled */
2300 if ( reneg->len != 0 ) {
2301 DBGC ( tls, "TLS %p server provided non-empty initial "
2302 "renegotiation\n", tls );
2303 return -EPERM_RENEG_VERIFY;
2304 }
2305 tls->secure_renegotiation = 1;
2306 }
2307
2308 return 0;
2309}
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:365
#define EPERM_EMS
Definition tls.c:187
#define EINVAL_HELLO
Definition tls.c:67
static int tls_select_cipher(struct tls_connection *tls, unsigned int cipher_suite)
Select next cipher suite.
Definition tls.c:940
#define EPROTO_VERSION
Definition tls.c:191
#define EPERM_RENEG_VERIFY
Definition tls.c:179

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

2320 {
2321 const struct {
2323 uint16_t len;
2324 uint8_t ticket[0];
2325 } __attribute__ (( packed )) *new_session_ticket = data;
2326 size_t ticket_len;
2327
2328 /* Parse header */
2329 if ( sizeof ( *new_session_ticket ) > len ) {
2330 DBGC ( tls, "TLS %p received underlength New Session Ticket\n",
2331 tls );
2332 DBGC_HD ( tls, data, len );
2333 return -EINVAL_TICKET;
2334 }
2335 ticket_len = ntohs ( new_session_ticket->len );
2336 if ( ticket_len > ( len - sizeof ( *new_session_ticket ) ) ) {
2337 DBGC ( tls, "TLS %p received overlength New Session Ticket\n",
2338 tls );
2339 DBGC_HD ( tls, data, len );
2340 return -EINVAL_TICKET;
2341 }
2342
2343 /* Free any unapplied new session ticket */
2344 free ( tls->new_session_ticket );
2345 tls->new_session_ticket = NULL;
2346 tls->new_session_ticket_len = 0;
2347
2348 /* Record ticket */
2349 tls->new_session_ticket = malloc ( ticket_len );
2350 if ( ! tls->new_session_ticket )
2351 return -ENOMEM;
2352 memcpy ( tls->new_session_ticket, new_session_ticket->ticket,
2353 ticket_len );
2354 tls->new_session_ticket_len = ticket_len;
2355 DBGC ( tls, "TLS %p new session ticket:\n", tls );
2356 DBGC_HDA ( tls, 0, tls->new_session_ticket,
2358
2359 return 0;
2360}
size_t new_session_ticket_len
Length of new session ticket.
Definition tls.h:451
#define EINVAL_TICKET
Definition tls.c:107
u32 lifetime
For Lifetime-type KDEs, the lifetime in seconds.
Definition wpa.h:27

References __attribute__, data, DBGC, DBGC_HD, DBGC_HDA, EINVAL_TICKET, ENOMEM, 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 2370 of file tls.c.

2371 {
2372 size_t remaining = len;
2373 int rc;
2374
2375 /* Free any existing certificate chain */
2376 memset ( &tls->server.key, 0, sizeof ( tls->server.key ) );
2377 x509_chain_put ( tls->server.chain );
2378 tls->server.chain = NULL;
2379
2380 /* Create certificate chain */
2381 tls->server.chain = x509_alloc_chain();
2382 if ( ! tls->server.chain ) {
2383 rc = -ENOMEM_CHAIN;
2384 goto err_alloc_chain;
2385 }
2386
2387 /* Add certificates to chain */
2388 while ( remaining ) {
2389 const struct {
2391 uint8_t data[0];
2392 } __attribute__ (( packed )) *certificate = data;
2393 size_t certificate_len;
2394 size_t record_len;
2395 struct x509_certificate *cert;
2396
2397 /* Parse header */
2398 if ( sizeof ( *certificate ) > remaining ) {
2399 DBGC ( tls, "TLS %p underlength certificate:\n", tls );
2400 DBGC_HDA ( tls, 0, data, remaining );
2402 goto err_underlength;
2403 }
2404 certificate_len = tls_uint24 ( &certificate->length );
2405 if ( certificate_len > ( remaining - sizeof ( *certificate ) )){
2406 DBGC ( tls, "TLS %p overlength certificate:\n", tls );
2407 DBGC_HDA ( tls, 0, data, remaining );
2409 goto err_overlength;
2410 }
2411 record_len = ( sizeof ( *certificate ) + certificate_len );
2412
2413 /* Add certificate to chain */
2414 if ( ( rc = x509_append_raw ( tls->server.chain,
2415 certificate->data,
2416 certificate_len ) ) != 0 ) {
2417 DBGC ( tls, "TLS %p could not append certificate: %s\n",
2418 tls, strerror ( rc ) );
2419 DBGC_HDA ( tls, 0, data, remaining );
2420 goto err_parse;
2421 }
2422 cert = x509_last ( tls->server.chain );
2423 DBGC ( tls, "TLS %p found certificate %s\n",
2424 tls, x509_name ( cert ) );
2425
2426 /* Move to next certificate in list */
2427 data += record_len;
2428 remaining -= record_len;
2429 }
2430
2431 return 0;
2432
2433 err_parse:
2434 err_overlength:
2435 err_underlength:
2436 memset ( &tls->server.key, 0, sizeof ( tls->server.key ) );
2437 x509_chain_put ( tls->server.chain );
2438 tls->server.chain = NULL;
2439 err_alloc_chain:
2440 return rc;
2441}
#define ENOMEM_CHAIN
Definition tls.c:127
#define EINVAL_CERTIFICATE
Definition tls.c:71
static unsigned long tls_uint24(const tls24_t *field24)
Extract 24-bit field value.
Definition tls.c:237
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 2451 of file tls.c.

2452 {
2453 const struct {
2455 uint8_t certificates[0];
2456 } __attribute__ (( packed )) *certificate = data;
2457 size_t certificates_len;
2458 int rc;
2459
2460 /* Parse header */
2461 if ( sizeof ( *certificate ) > len ) {
2462 DBGC ( tls, "TLS %p received underlength Server Certificate\n",
2463 tls );
2464 DBGC_HD ( tls, data, len );
2465 return -EINVAL_CERTIFICATES;
2466 }
2467 certificates_len = tls_uint24 ( &certificate->length );
2468 if ( certificates_len > ( len - sizeof ( *certificate ) ) ) {
2469 DBGC ( tls, "TLS %p received overlength Server Certificate\n",
2470 tls );
2471 DBGC_HD ( tls, data, len );
2472 return -EINVAL_CERTIFICATES;
2473 }
2474
2475 /* Parse certificate chain */
2476 if ( ( rc = tls_parse_chain ( tls, certificate->certificates,
2477 certificates_len ) ) != 0 )
2478 return rc;
2479
2480 return 0;
2481}
#define EINVAL_CERTIFICATES
Definition tls.c:75
static int tls_parse_chain(struct tls_connection *tls, const void *data, size_t len)
Parse certificate chain.
Definition tls.c:2370

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

2492 {
2493
2494 /* Free any existing server key exchange record */
2495 free ( tls->server.exchange );
2496 tls->server.exchange_len = 0;
2497
2498 /* Allocate copy of server key exchange record */
2499 tls->server.exchange = malloc ( len );
2500 if ( ! tls->server.exchange )
2501 return -ENOMEM;
2502
2503 /* Store copy of server key exchange record for later
2504 * processing. We cannot verify the signature at this point
2505 * since the certificate validation will not yet have
2506 * completed.
2507 */
2508 memcpy ( tls->server.exchange, data, len );
2509 tls->server.exchange_len = len;
2510
2511 return 0;
2512}

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

2524 {
2525 struct x509_certificate *cert;
2526 int rc;
2527
2528 /* We can only send a single certificate, so there is no point
2529 * in parsing the Certificate Request.
2530 */
2531
2532 /* Free any existing client certificate chain */
2533 x509_chain_put ( tls->client.chain );
2534 tls->client.chain = NULL;
2535
2536 /* Create client certificate chain */
2537 tls->client.chain = x509_alloc_chain();
2538 if ( ! tls->client.chain ) {
2539 rc = -ENOMEM;
2540 goto err_alloc;
2541 }
2542
2543 /* Determine client certificate to be sent, if any */
2544 cert = x509_find_key ( NULL, tls->client.key );
2545 if ( cert ) {
2546 DBGC ( tls, "TLS %p selected client certificate %s\n",
2547 tls, x509_name ( cert ) );
2548
2549 /* Append client certificate to chain */
2550 if ( ( rc = x509_append ( tls->client.chain, cert ) ) != 0 )
2551 goto err_append;
2552
2553 /* Append any relevant issuer certificates */
2554 if ( ( rc = x509_auto_append ( tls->client.chain,
2555 &certstore ) ) != 0 )
2556 goto err_auto_append;
2557 } else {
2558
2559 /* Send an empty certificate chain */
2560 DBGC ( tls, "TLS %p could not find certificate corresponding "
2561 "to private key\n", tls );
2562 }
2563
2564 return 0;
2565
2566 err_auto_append:
2567 err_append:
2568 x509_chain_put ( tls->client.chain );
2569 tls->client.chain = NULL;
2570 err_alloc:
2571 return rc;
2572}
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 2582 of file tls.c.

2583 {
2584 const struct {
2585 char next[0];
2586 } __attribute__ (( packed )) *hello_done = data;
2587 int rc;
2588
2589 /* Sanity check */
2590 if ( sizeof ( *hello_done ) != len ) {
2591 DBGC ( tls, "TLS %p received overlength Server Hello Done\n",
2592 tls );
2593 DBGC_HD ( tls, data, len );
2594 return -EINVAL_HELLO_DONE;
2595 }
2596
2597 /* Begin certificate validation */
2598 if ( ( rc = create_validator ( &tls->server.validator,
2599 tls->server.chain,
2600 tls->server.root ) ) != 0 ) {
2601 DBGC ( tls, "TLS %p could not start certificate validation: "
2602 "%s\n", tls, strerror ( rc ) );
2603 return rc;
2604 }
2605 pending_get ( &tls->server.validation );
2606
2607 return 0;
2608}
#define EINVAL_HELLO_DONE
Definition tls.c:79
int create_validator(struct interface *job, struct x509_chain *chain, struct x509_root *root)
Instantiate a certificate validator.
Definition validator.c:760

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

Referenced by tls_new_handshake().

◆ tls_new_finished()

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

Receive new Finished handshake record.

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

Definition at line 2618 of file tls.c.

2619 {
2620 struct tls_session *session = tls->session;
2621 struct digest_algorithm *digest = tls->handshake_digest;
2622 const struct {
2623 uint8_t verify_data[ sizeof ( tls->verify.server ) ];
2624 char next[0];
2625 } __attribute__ (( packed )) *finished = data;
2626 uint8_t digest_out[ digest->digestsize ];
2627
2628 /* Sanity check */
2629 if ( sizeof ( *finished ) != len ) {
2630 DBGC ( tls, "TLS %p received overlength Finished\n", tls );
2631 DBGC_HD ( tls, data, len );
2632 return -EINVAL_FINISHED;
2633 }
2634
2635 /* Verify data */
2636 tls_verify_handshake ( tls, digest_out );
2637 tls_prf_label ( tls, &tls->master_secret, sizeof ( tls->master_secret ),
2638 tls->verify.server, sizeof ( tls->verify.server ),
2639 "server finished", digest_out, sizeof ( digest_out ) );
2640 if ( memcmp ( tls->verify.server, finished->verify_data,
2641 sizeof ( tls->verify.server ) ) != 0 ) {
2642 DBGC ( tls, "TLS %p verification failed\n", tls );
2643 return -EPERM_VERIFY;
2644 }
2645
2646 /* Mark server as finished */
2647 pending_put ( &tls->server.negotiation );
2648
2649 /* If we are resuming a session (i.e. if the server Finished
2650 * arrives before the client Finished is sent), then schedule
2651 * transmission of Change Cipher and Finished.
2652 */
2653 if ( is_pending ( &tls->client.negotiation ) ) {
2655 tls_tx_resume ( tls );
2656 }
2657
2658 /* Record session ID, ticket, and master secret, if applicable */
2659 if ( tls->session_id_len || tls->new_session_ticket_len ) {
2660 memcpy ( session->master_secret, tls->master_secret,
2661 sizeof ( session->master_secret ) );
2663 }
2664 if ( tls->session_id_len ) {
2665 session->id_len = tls->session_id_len;
2666 memcpy ( session->id, tls->session_id, sizeof ( session->id ) );
2667 }
2668 if ( tls->new_session_ticket_len ) {
2669 free ( session->ticket );
2670 session->ticket = tls->new_session_ticket;
2671 session->ticket_len = tls->new_session_ticket_len;
2672 tls->new_session_ticket = NULL;
2673 tls->new_session_ticket_len = 0;
2674 }
2675
2676 /* Move to end of session's connection list and allow other
2677 * connections to start making progress.
2678 */
2679 list_del ( &tls->list );
2680 list_add_tail ( &tls->list, &session->conn );
2681 tls_tx_resume_all ( session );
2682
2683 /* Send notification of a window change */
2685
2686 return 0;
2687}
#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:355
size_t id_len
Length of session ID.
Definition tls.h:357
uint8_t master_secret[48]
Master secret.
Definition tls.h:363
uint8_t server[12]
Server verification data.
Definition tls.h:167
#define EINVAL_FINISHED
Definition tls.c:83
#define EPERM_VERIFY
Definition tls.c:171
@ TLS_TX_FINISHED
Definition tls.h:183
@ TLS_TX_CHANGE_CIPHER
Definition tls.h:182
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 2696 of file tls.c.

2697 {
2698 size_t remaining;
2699 int rc;
2700
2701 while ( ( remaining = iob_len ( iobuf ) ) ) {
2702 const struct {
2703 uint8_t type;
2705 uint8_t payload[0];
2706 } __attribute__ (( packed )) *handshake = iobuf->data;
2707 const void *payload;
2708 size_t payload_len;
2709 size_t record_len;
2710
2711 /* Parse header */
2712 if ( sizeof ( *handshake ) > remaining ) {
2713 /* Leave remaining fragment unconsumed */
2714 break;
2715 }
2716 payload_len = tls_uint24 ( &handshake->length );
2717 if ( payload_len > ( remaining - sizeof ( *handshake ) ) ) {
2718 /* Leave remaining fragment unconsumed */
2719 break;
2720 }
2721 payload = &handshake->payload;
2722 record_len = ( sizeof ( *handshake ) + payload_len );
2723
2724 /* Handle payload */
2725 switch ( handshake->type ) {
2726 case TLS_HELLO_REQUEST:
2727 rc = tls_new_hello_request ( tls, payload,
2728 payload_len );
2729 break;
2730 case TLS_SERVER_HELLO:
2731 rc = tls_new_server_hello ( tls, payload, payload_len );
2732 break;
2734 rc = tls_new_session_ticket ( tls, payload,
2735 payload_len );
2736 break;
2737 case TLS_CERTIFICATE:
2738 rc = tls_new_certificate ( tls, payload, payload_len );
2739 break;
2741 rc = tls_new_server_key_exchange ( tls, payload,
2742 payload_len );
2743 break;
2745 rc = tls_new_certificate_request ( tls, payload,
2746 payload_len );
2747 break;
2749 rc = tls_new_server_hello_done ( tls, payload,
2750 payload_len );
2751 break;
2752 case TLS_FINISHED:
2753 rc = tls_new_finished ( tls, payload, payload_len );
2754 break;
2755 default:
2756 DBGC ( tls, "TLS %p ignoring handshake type %d\n",
2757 tls, handshake->type );
2758 rc = 0;
2759 break;
2760 }
2761
2762 /* Add to handshake digest (except for Hello Requests,
2763 * which are explicitly excluded).
2764 */
2765 if ( handshake->type != TLS_HELLO_REQUEST )
2766 tls_add_handshake ( tls, handshake, record_len );
2767
2768 /* Abort on failure */
2769 if ( rc != 0 )
2770 return rc;
2771
2772 /* Move to next handshake record */
2773 iob_pull ( iobuf, record_len );
2774 }
2775
2776 return 0;
2777}
static int tls_new_finished(struct tls_connection *tls, const void *data, size_t len)
Receive new Finished handshake record.
Definition tls.c:2618
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:2117
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:2522
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:2319
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:2086
static int tls_new_certificate(struct tls_connection *tls, const void *data, size_t len)
Receive new Certificate handshake record.
Definition tls.c:2451
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:2582
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:2491
#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 2786 of file tls.c.

2787 {
2788
2789 /* RFC4346 says that we should just ignore unknown record types */
2790 iob_pull ( iobuf, iob_len ( iobuf ) );
2791 return 0;
2792}

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

2802 {
2803 struct io_buffer *iobuf;
2804 int rc;
2805
2806 /* Fail unless we are ready to receive data */
2807 if ( ! tls_ready ( tls ) )
2808 return -ENOTCONN;
2809
2810 /* Deliver each I/O buffer in turn */
2811 while ( ( iobuf = list_first_entry ( rx_data, struct io_buffer,
2812 list ) ) ) {
2813 list_del ( &iobuf->list );
2814 if ( ( rc = xfer_deliver_iob ( &tls->plainstream,
2815 iobuf ) ) != 0 ) {
2816 DBGC ( tls, "TLS %p could not deliver data: "
2817 "%s\n", tls, strerror ( rc ) );
2818 return rc;
2819 }
2820 }
2821
2822 return 0;
2823}
#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 2833 of file tls.c.

2834 {
2835 int ( * handler ) ( struct tls_connection *tls,
2836 struct io_buffer *iobuf );
2837 struct io_buffer *tmp = NULL;
2838 struct io_buffer **iobuf;
2839 int rc;
2840
2841 /* Deliver data records as-is to the plainstream interface */
2842 if ( type == TLS_TYPE_DATA )
2843 return tls_new_data ( tls, rx_data );
2844
2845 /* Determine handler and fragment buffer */
2846 iobuf = &tmp;
2847 switch ( type ) {
2849 handler = tls_new_change_cipher;
2850 break;
2851 case TLS_TYPE_ALERT:
2852 handler = tls_new_alert;
2853 break;
2854 case TLS_TYPE_HANDSHAKE:
2855 handler = tls_new_handshake;
2856 iobuf = &tls->rx.handshake;
2857 break;
2858 default:
2859 DBGC ( tls, "TLS %p unknown record type %d\n", tls, type );
2860 handler = tls_new_unknown;
2861 break;
2862 }
2863
2864 /* Merge into a single I/O buffer */
2865 if ( *iobuf )
2866 list_add ( &(*iobuf)->list, rx_data );
2867 *iobuf = iob_concatenate ( rx_data );
2868 if ( ! *iobuf ) {
2869 DBGC ( tls, "TLS %p could not concatenate non-data record "
2870 "type %d\n", tls, type );
2872 goto err_concatenate;
2873 }
2874
2875 /* Handle record */
2876 if ( ( rc = handler ( tls, *iobuf ) ) != 0 )
2877 goto err_handle;
2878
2879 /* Discard I/O buffer if empty */
2880 if ( ! iob_len ( *iobuf ) ) {
2881 free_iob ( *iobuf );
2882 *iobuf = NULL;
2883 }
2884
2885 /* Sanity check */
2886 assert ( tmp == NULL );
2887
2888 return 0;
2889
2890 err_handle:
2891 free_iob ( *iobuf );
2892 *iobuf = NULL;
2893 err_concatenate:
2894 return rc;
2895}
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:2009
#define ENOMEM_RX_CONCAT
Definition tls.c:143
static int tls_new_unknown(struct tls_connection *tls __unused, struct io_buffer *iobuf)
Receive new unknown record.
Definition tls.c:2786
static int tls_new_data(struct tls_connection *tls, struct list_head *rx_data)
Receive new data record.
Definition tls.c:2801
static int tls_new_handshake(struct tls_connection *tls, struct io_buffer *iobuf)
Receive new Handshake record.
Definition tls.c:2696
static int tls_new_alert(struct tls_connection *tls, struct io_buffer *iobuf)
Receive new Alert record.
Definition tls.c:2044
#define TLS_TYPE_ALERT
Alert content type.
Definition tls.h:60
#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 2911 of file tls.c.

2912 {
2913 struct tls_cipher_suite *suite = cipherspec->suite;
2914 struct digest_algorithm *digest = suite->digest;
2915
2916 hmac_init ( digest, ctx, cipherspec->mac_secret, suite->mac_len );
2917 hmac_update ( digest, ctx, authhdr, sizeof ( *authhdr ) );
2918}

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

2929 {
2930 struct digest_algorithm *digest = cipherspec->suite->digest;
2931
2932 hmac_update ( digest, ctx, data, len );
2933}

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

2943 {
2944 struct digest_algorithm *digest = cipherspec->suite->digest;
2945
2946 hmac_final ( digest, ctx, hmac );
2947}

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

2960 {
2961 struct digest_algorithm *digest = cipherspec->suite->digest;
2962 uint8_t ctx[ hmac_ctxsize ( digest ) ];
2963
2964 tls_hmac_init ( cipherspec, ctx, authhdr );
2965 tls_hmac_update ( cipherspec, ctx, data, len );
2966 tls_hmac_final ( cipherspec, ctx, hmac );
2967}
static void tls_hmac_init(struct tls_cipherspec *cipherspec, void *ctx, struct tls_auth_header *authhdr)
Initialise HMAC.
Definition tls.c:2911
static void tls_hmac_final(struct tls_cipherspec *cipherspec, void *ctx, void *hmac)
Finalise HMAC.
Definition tls.c:2942
static void tls_hmac_update(struct tls_cipherspec *cipherspec, void *ctx, const void *data, size_t len)
Update HMAC.
Definition tls.c:2928

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

2979 {
2980 struct digest_algorithm *digest = cipherspec->suite->digest;
2981 uint8_t ctx[ hmac_ctxsize ( digest ) ];
2982 struct io_buffer *iobuf;
2983
2984 tls_hmac_init ( cipherspec, ctx, authhdr );
2985 list_for_each_entry ( iobuf, list, list ) {
2986 tls_hmac_update ( cipherspec, ctx, iobuf->data,
2987 iob_len ( iobuf ) );
2988 }
2989 tls_hmac_final ( cipherspec, ctx, hmac );
2990}

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

2999 {
3000 struct tls_cipherspec *cipherspec = &tls->tx.cipherspec.active;
3001 struct tls_cipher_suite *suite = cipherspec->suite;
3002 struct cipher_algorithm *cipher = suite->cipher;
3003 struct tls_header *tlshdr;
3004 unsigned int count;
3005 size_t each;
3006
3007 /* Calculate number of records (allowing for zero-length records) */
3008 count = ( len ? ( ( len + TLS_TX_BUFSIZE - 1 ) / TLS_TX_BUFSIZE ) : 1 );
3009
3010 /* Calculate maximum additional length per record */
3011 each = ( sizeof ( *tlshdr ) + suite->record_iv_len + suite->mac_len +
3012 ( is_block_cipher ( cipher ) ? cipher->blocksize : 0 ) +
3013 cipher->authsize );
3014
3015 /* Calculate maximum total additional length */
3016 return ( count * each );
3017}
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 3222 of file tls.c.

3223 {
3224 uint8_t *padding;
3225 unsigned int pad;
3226 unsigned int i;
3227 size_t len;
3228
3229 /* Extract and verify padding */
3230 padding = ( iobuf->tail - 1 );
3231 pad = *padding;
3232 len = ( pad + 1 );
3233 if ( len > iob_len ( iobuf ) ) {
3234 DBGC ( tls, "TLS %p received underlength padding\n", tls );
3235 DBGC_HD ( tls, iobuf->data, iob_len ( iobuf ) );
3236 return -EINVAL_PADDING;
3237 }
3238 for ( i = 0 ; i < pad ; i++ ) {
3239 if ( *(--padding) != pad ) {
3240 DBGC ( tls, "TLS %p received bad padding\n", tls );
3241 DBGC_HD ( tls, iobuf->data, iob_len ( iobuf ) );
3242 return -EINVAL_PADDING;
3243 }
3244 }
3245
3246 return len;
3247}
u32 pad[9]
Padding.
Definition ar9003_mac.h:23
void * tail
End of data.
Definition iobuf.h:55
#define EINVAL_PADDING
Definition tls.c:95

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

Referenced by tls_new_ciphertext().

◆ tls_new_ciphertext()

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

Receive new ciphertext record.

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

Definition at line 3257 of file tls.c.

3259 {
3260 struct tls_cipherspec *cipherspec = &tls->rx.cipherspec.active;
3261 struct tls_cipher_suite *suite = cipherspec->suite;
3262 struct cipher_algorithm *cipher = suite->cipher;
3263 struct digest_algorithm *digest = suite->digest;
3264 size_t len = ntohs ( tlshdr->length );
3265 struct {
3266 uint8_t fixed[suite->fixed_iv_len];
3267 uint8_t record[suite->record_iv_len];
3268 } __attribute__ (( packed )) iv;
3269 struct tls_auth_header authhdr;
3270 uint8_t verify_mac[digest->digestsize];
3271 uint8_t verify_auth[cipher->authsize];
3272 struct io_buffer *first;
3273 struct io_buffer *last;
3274 struct io_buffer *iobuf;
3275 void *mac;
3276 void *auth;
3277 size_t check_len;
3278 int pad_len;
3279 int rc;
3280
3281 /* Locate first and last data buffers */
3282 assert ( ! list_empty ( rx_data ) );
3283 first = list_first_entry ( rx_data, struct io_buffer, list );
3284 last = list_last_entry ( rx_data, struct io_buffer, list );
3285
3286 /* Extract initialisation vector */
3287 if ( iob_len ( first ) < sizeof ( iv.record ) ) {
3288 DBGC ( tls, "TLS %p received underlength IV\n", tls );
3289 DBGC_HD ( tls, first->data, iob_len ( first ) );
3290 return -EINVAL_IV;
3291 }
3292 memcpy ( iv.fixed, cipherspec->fixed_iv, sizeof ( iv.fixed ) );
3293 memcpy ( iv.record, first->data, sizeof ( iv.record ) );
3294 iob_pull ( first, sizeof ( iv.record ) );
3295 len -= sizeof ( iv.record );
3296
3297 /* Extract unencrypted authentication tag */
3298 if ( iob_len ( last ) < cipher->authsize ) {
3299 DBGC ( tls, "TLS %p received underlength authentication tag\n",
3300 tls );
3301 DBGC_HD ( tls, last->data, iob_len ( last ) );
3302 return -EINVAL_MAC;
3303 }
3304 iob_unput ( last, cipher->authsize );
3305 len -= cipher->authsize;
3306 auth = last->tail;
3307
3308 /* Construct authentication data */
3309 authhdr.seq = cpu_to_be64 ( tls->rx.seq );
3310 authhdr.header.type = tlshdr->type;
3311 authhdr.header.version = tlshdr->version;
3312 authhdr.header.length = htons ( len );
3313
3314 /* Set initialisation vector */
3315 cipher_setiv ( cipher, cipherspec->cipher_ctx, &iv, sizeof ( iv ) );
3316
3317 /* Process authentication data, if applicable */
3318 if ( is_auth_cipher ( cipher ) ) {
3319 cipher_decrypt ( cipher, cipherspec->cipher_ctx, &authhdr,
3320 NULL, sizeof ( authhdr ) );
3321 }
3322
3323 /* Decrypt the received data */
3324 check_len = 0;
3325 list_for_each_entry ( iobuf, &tls->rx.data, list ) {
3326 cipher_decrypt ( cipher, cipherspec->cipher_ctx,
3327 iobuf->data, iobuf->data, iob_len ( iobuf ) );
3328 check_len += iob_len ( iobuf );
3329 }
3330 assert ( check_len == len );
3331
3332 /* Strip block padding, if applicable */
3333 if ( is_block_cipher ( cipher ) ) {
3334 pad_len = tls_verify_padding ( tls, last );
3335 if ( pad_len < 0 ) {
3336 /* Assume zero padding length to avoid timing attacks */
3337 pad_len = 0;
3338 }
3339 iob_unput ( last, pad_len );
3340 len -= pad_len;
3341 }
3342
3343 /* Extract decrypted MAC */
3344 if ( iob_len ( last ) < suite->mac_len ) {
3345 DBGC ( tls, "TLS %p received underlength MAC\n", tls );
3346 DBGC_HD ( tls, last->data, iob_len ( last ) );
3347 return -EINVAL_MAC;
3348 }
3349 iob_unput ( last, suite->mac_len );
3350 len -= suite->mac_len;
3351 mac = last->tail;
3352
3353 /* Dump received data */
3354 DBGC2 ( tls, "Received plaintext data:\n" );
3355 check_len = 0;
3356 list_for_each_entry ( iobuf, rx_data, list ) {
3357 DBGC2_HD ( tls, iobuf->data, iob_len ( iobuf ) );
3358 check_len += iob_len ( iobuf );
3359 }
3360 assert ( check_len == len );
3361
3362 /* Generate MAC */
3363 authhdr.header.length = htons ( len );
3364 if ( suite->mac_len )
3365 tls_hmac_list ( cipherspec, &authhdr, rx_data, verify_mac );
3366
3367 /* Generate authentication tag */
3368 cipher_auth ( cipher, cipherspec->cipher_ctx, verify_auth );
3369
3370 /* Verify MAC */
3371 if ( memcmp ( mac, verify_mac, suite->mac_len ) != 0 ) {
3372 DBGC ( tls, "TLS %p failed MAC verification\n", tls );
3373 return -EINVAL_MAC;
3374 }
3375
3376 /* Verify authentication tag */
3377 if ( memcmp ( auth, verify_auth, cipher->authsize ) != 0 ) {
3378 DBGC ( tls, "TLS %p failed authentication tag verification\n",
3379 tls );
3380 return -EINVAL_MAC;
3381 }
3382
3383 /* Process plaintext record */
3384 if ( ( rc = tls_new_record ( tls, tlshdr->type, rx_data ) ) != 0 )
3385 return rc;
3386
3387 return 0;
3388}
#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:91
static void tls_hmac_list(struct tls_cipherspec *cipherspec, struct tls_auth_header *authhdr, struct list_head *list, void *hmac)
Calculate HMAC over list of I/O buffers.
Definition tls.c:2977
#define EINVAL_MAC
Definition tls.c:103
static int tls_verify_padding(struct tls_connection *tls, struct io_buffer *iobuf)
Verify block padding.
Definition tls.c:3222
static int tls_new_record(struct tls_connection *tls, unsigned int type, struct list_head *rx_data)
Receive new record.
Definition tls.c:2833

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

3403 {
3404
3405 /* Block window unless we are ready to accept data */
3406 if ( ! tls_ready ( tls ) )
3407 return 0;
3408
3409 return xfer_window ( &tls->cipherstream );
3410}
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 3420 of file tls.c.

3422 {
3423 int rc;
3424
3425 /* Refuse unless we are ready to accept data */
3426 if ( ! tls_ready ( tls ) ) {
3427 rc = -ENOTCONN;
3428 goto done;
3429 }
3430
3431 /* Send data record */
3432 if ( ( rc = tls_send_record ( tls, TLS_TYPE_DATA,
3433 iob_disown ( iobuf ) ) ) != 0 )
3434 goto done;
3435
3436 done:
3437 free_iob ( iobuf );
3438 return rc;
3439}
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 3448 of file tls.c.

3449 {
3450
3451 /* Return cipherstream or validator progress as applicable */
3452 if ( is_pending ( &tls->server.validation ) ) {
3453 return job_progress ( &tls->server.validator, progress );
3454 } else {
3455 return job_progress ( &tls->cipherstream, progress );
3456 }
3457}
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 3488 of file tls.c.

3488 {
3489 struct tls_cipherspec *cipherspec = &tls->rx.cipherspec.active;
3490 struct cipher_algorithm *cipher = cipherspec->suite->cipher;
3491 size_t iv_len = cipherspec->suite->record_iv_len;
3492 size_t data_len = ntohs ( tls->rx.header.length );
3493 size_t remaining = data_len;
3494 size_t frag_len;
3495 size_t reserve;
3496 struct io_buffer *iobuf;
3497 struct io_buffer *tmp;
3498 int rc;
3499
3500 /* Sanity check */
3501 assert ( ( TLS_RX_BUFSIZE % cipher->alignsize ) == 0 );
3502
3503 /* Calculate alignment reservation at start of first data buffer */
3504 reserve = ( ( -iv_len ) & ( cipher->alignsize - 1 ) );
3505 remaining += reserve;
3506
3507 /* Allocate data buffers now that we know the length */
3508 assert ( list_empty ( &tls->rx.data ) );
3509 while ( remaining ) {
3510
3511 /* Calculate fragment length. Ensure that no block is
3512 * smaller than TLS_RX_MIN_BUFSIZE (by increasing the
3513 * allocation length if necessary).
3514 */
3515 frag_len = remaining;
3516 if ( frag_len > TLS_RX_BUFSIZE )
3517 frag_len = TLS_RX_BUFSIZE;
3518 remaining -= frag_len;
3519 if ( remaining < TLS_RX_MIN_BUFSIZE ) {
3520 frag_len += remaining;
3521 remaining = 0;
3522 }
3523
3524 /* Allocate buffer */
3525 iobuf = alloc_iob_raw ( frag_len, TLS_RX_ALIGN, 0 );
3526 if ( ! iobuf ) {
3527 DBGC ( tls, "TLS %p could not allocate %zd of %zd "
3528 "bytes for receive buffer\n", tls,
3529 remaining, data_len );
3530 rc = -ENOMEM_RX_DATA;
3531 goto err;
3532 }
3533
3534 /* Ensure tailroom is exactly what we asked for. This
3535 * will result in unaligned I/O buffers when the
3536 * fragment length is unaligned, which can happen only
3537 * before we switch to using a block cipher.
3538 */
3539 iob_reserve ( iobuf, ( iob_tailroom ( iobuf ) - frag_len ) );
3540
3541 /* Ensure first buffer length will be aligned to a
3542 * multiple of the cipher alignment size after
3543 * stripping the record IV.
3544 */
3545 iob_reserve ( iobuf, reserve );
3546 reserve = 0;
3547
3548 /* Add I/O buffer to list */
3549 list_add_tail ( &iobuf->list, &tls->rx.data );
3550 }
3551
3552 /* Move to data state */
3553 tls->rx.state = TLS_RX_DATA;
3554
3555 return 0;
3556
3557 err:
3558 list_for_each_entry_safe ( iobuf, tmp, &tls->rx.data, list ) {
3559 list_del ( &iobuf->list );
3560 free_iob ( iobuf );
3561 }
3562 return rc;
3563}
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:390
struct tls_header header
Current received record header.
Definition tls.h:392
#define ENOMEM_RX_DATA
Definition tls.c:139
#define TLS_RX_MIN_BUFSIZE
Minimum RX I/O buffer size.
Definition tls.h:510
#define TLS_RX_ALIGN
RX I/O buffer alignment.
Definition tls.h:513
@ TLS_RX_DATA
Definition tls.h:173
#define TLS_RX_BUFSIZE
RX I/O buffer size.
Definition tls.h:502
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 3571 of file tls.c.

3571 {
3572 struct io_buffer *iobuf;
3573 int rc;
3574
3575 /* Move current buffer to end of list */
3576 iobuf = list_first_entry ( &tls->rx.data, struct io_buffer, list );
3577 list_del ( &iobuf->list );
3578 list_add_tail ( &iobuf->list, &tls->rx.data );
3579
3580 /* Continue receiving data if any space remains */
3581 iobuf = list_first_entry ( &tls->rx.data, struct io_buffer, list );
3582 if ( iob_tailroom ( iobuf ) )
3583 return 0;
3584
3585 /* Process record */
3586 if ( ( rc = tls_new_ciphertext ( tls, &tls->rx.header,
3587 &tls->rx.data ) ) != 0 )
3588 return rc;
3589
3590 /* Increment RX sequence number */
3591 tls->rx.seq += 1;
3592
3593 /* Return to header state */
3594 assert ( list_empty ( &tls->rx.data ) );
3595 tls->rx.state = TLS_RX_HEADER;
3596 iob_unput ( &tls->rx.iobuf, sizeof ( tls->rx.header ) );
3597
3598 return 0;
3599}
struct io_buffer iobuf
Current received record header (static I/O buffer)
Definition tls.h:394
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:3257
@ TLS_RX_HEADER
Definition tls.h:172

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

3607 {
3608
3609 /* Open window until we are ready to accept data */
3610 if ( ! tls_ready ( tls ) )
3611 return -1UL;
3612
3613 return xfer_window ( &tls->plainstream );
3614}

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

3626 {
3627 size_t frag_len;
3628 int ( * process ) ( struct tls_connection *tls );
3629 struct io_buffer *dest;
3630 int rc;
3631
3632 while ( iob_len ( iobuf ) ) {
3633
3634 /* Select buffer according to current state */
3635 switch ( tls->rx.state ) {
3636 case TLS_RX_HEADER:
3637 dest = &tls->rx.iobuf;
3639 break;
3640 case TLS_RX_DATA:
3641 dest = list_first_entry ( &tls->rx.data,
3642 struct io_buffer, list );
3643 assert ( dest != NULL );
3645 break;
3646 default:
3647 assert ( 0 );
3649 goto done;
3650 }
3651
3652 /* Copy data portion to buffer */
3653 frag_len = iob_len ( iobuf );
3654 if ( frag_len > iob_tailroom ( dest ) )
3655 frag_len = iob_tailroom ( dest );
3656 memcpy ( iob_put ( dest, frag_len ), iobuf->data, frag_len );
3657 iob_pull ( iobuf, frag_len );
3658
3659 /* Process data if buffer is now full */
3660 if ( iob_tailroom ( dest ) == 0 ) {
3661 if ( ( rc = process ( tls ) ) != 0 ) {
3662 tls_close ( tls, rc );
3663 goto done;
3664 }
3665 }
3666 }
3667 rc = 0;
3668
3669 done:
3670 free_iob ( iobuf );
3671 return rc;
3672}
if(len >=6 *4) __asm__ __volatile__("movsl" if(len >=5 *4) __asm__ __volatile__("movsl" if(len >=4 *4) __asm__ __volatile__("movsl" if(len >=3 *4) __asm__ __volatile__("movsl" if(len >=2 *4) __asm__ __volatile__("movsl" if(len >=1 *4) __asm__ __volatile__("movsl" if((len % 4) >=2) __asm__ __volatile__("movsw" if((len % 2) >=1) __asm__ __volatile__("movsb" retur dest)
Definition string.h:151
A process.
Definition process.h:18
#define EINVAL_RX_STATE
Definition tls.c:99
static int tls_newdata_process_data(struct tls_connection *tls)
Handle received TLS data payload.
Definition tls.c:3571
static int tls_newdata_process_header(struct tls_connection *tls)
Handle received TLS header.
Definition tls.c:3488
static void tls_close(struct tls_connection *tls, int rc)
Finish with TLS connection.
Definition tls.c:422

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

3703 {
3704 struct tls_session *session = tls->session;
3705 struct x509_certificate *cert;
3706
3707 /* Mark validation as complete */
3708 pending_put ( &tls->server.validation );
3709
3710 /* Close validator interface */
3711 intf_restart ( &tls->server.validator, rc );
3712
3713 /* Check for validation failure */
3714 if ( rc != 0 ) {
3715 DBGC ( tls, "TLS %p certificate validation failed: %s\n",
3716 tls, strerror ( rc ) );
3717 goto err;
3718 }
3719 DBGC ( tls, "TLS %p certificate validation succeeded\n", tls );
3720
3721 /* Extract first certificate */
3722 cert = x509_first ( tls->server.chain );
3723 assert ( cert != NULL );
3724
3725 /* Verify server name */
3726 if ( ( rc = x509_check_name ( cert, session->name ) ) != 0 ) {
3727 DBGC ( tls, "TLS %p server certificate does not match %s: %s\n",
3728 tls, session->name, strerror ( rc ) );
3729 goto err;
3730 }
3731
3732 /* Extract the now trusted server public key */
3733 memcpy ( &tls->server.key, &cert->subject.public_key.raw,
3734 sizeof ( tls->server.key ) );
3735
3736 /* Schedule transmission of applicable handshake messages */
3740 if ( tls->client.chain ) {
3742 if ( ! list_empty ( &tls->client.chain->links ) )
3744 }
3745 tls_tx_resume ( tls );
3746
3747 return;
3748
3749 err:
3750 tls_close ( tls, rc );
3751 return;
3752}
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:180
@ TLS_TX_CERTIFICATE_VERIFY
Definition tls.h:181
@ TLS_TX_CERTIFICATE
Definition tls.h:179
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 3776 of file tls.c.

3776 {
3777 struct tls_session *session = tls->session;
3778 struct tls_connection *conn;
3779 int rc;
3780
3781 /* Wait for cipherstream to become ready */
3782 if ( ! xfer_window ( &tls->cipherstream ) )
3783 return;
3784
3785 /* Send first pending transmission */
3786 if ( tls->tx.pending & TLS_TX_CLIENT_HELLO ) {
3787 /* Serialise server negotiations within a session, to
3788 * provide a consistent view of session IDs and
3789 * session tickets.
3790 */
3791 list_for_each_entry ( conn, &session->conn, list ) {
3792 if ( conn == tls )
3793 break;
3794 if ( is_pending ( &conn->server.negotiation ) )
3795 return;
3796 }
3797 /* Record or generate session ID and associated master secret */
3798 if ( session->id_len ) {
3799 /* Attempt to resume an existing session */
3800 memcpy ( tls->session_id, session->id,
3801 sizeof ( tls->session_id ) );
3804 sizeof ( tls->master_secret ) );
3805 } else {
3806 /* No existing session: use a random session ID */
3807 assert ( sizeof ( tls->session_id ) ==
3808 sizeof ( tls->client.random ) );
3809 memcpy ( tls->session_id, &tls->client.random,
3810 sizeof ( tls->session_id ) );
3811 tls->session_id_len = sizeof ( tls->session_id );
3812 }
3813 /* Send Client Hello */
3814 if ( ( rc = tls_send_client_hello ( tls ) ) != 0 ) {
3815 DBGC ( tls, "TLS %p could not send Client Hello: %s\n",
3816 tls, strerror ( rc ) );
3817 goto err;
3818 }
3820 } else if ( tls->tx.pending & TLS_TX_CERTIFICATE ) {
3821 /* Send Certificate */
3822 if ( ( rc = tls_send_certificate ( tls ) ) != 0 ) {
3823 DBGC ( tls, "TLS %p cold not send Certificate: %s\n",
3824 tls, strerror ( rc ) );
3825 goto err;
3826 }
3828 } else if ( tls->tx.pending & TLS_TX_CLIENT_KEY_EXCHANGE ) {
3829 /* Send Client Key Exchange */
3830 if ( ( rc = tls_send_client_key_exchange ( tls ) ) != 0 ) {
3831 DBGC ( tls, "TLS %p could not send Client Key "
3832 "Exchange: %s\n", tls, strerror ( rc ) );
3833 goto err;
3834 }
3836 } else if ( tls->tx.pending & TLS_TX_CERTIFICATE_VERIFY ) {
3837 /* Send Certificate Verify */
3838 if ( ( rc = tls_send_certificate_verify ( tls ) ) != 0 ) {
3839 DBGC ( tls, "TLS %p could not send Certificate "
3840 "Verify: %s\n", tls, strerror ( rc ) );
3841 goto err;
3842 }
3844 } else if ( tls->tx.pending & TLS_TX_CHANGE_CIPHER ) {
3845 /* Send Change Cipher, and then change the cipher in use */
3846 if ( ( rc = tls_send_change_cipher ( tls ) ) != 0 ) {
3847 DBGC ( tls, "TLS %p could not send Change Cipher: "
3848 "%s\n", tls, strerror ( rc ) );
3849 goto err;
3850 }
3851 if ( ( rc = tls_change_cipher ( tls,
3852 &tls->tx.cipherspec ) ) != 0 ){
3853 DBGC ( tls, "TLS %p could not activate TX cipher: "
3854 "%s\n", tls, strerror ( rc ) );
3855 goto err;
3856 }
3857 tls->tx.seq = 0;
3859 } else if ( tls->tx.pending & TLS_TX_FINISHED ) {
3860 /* Send Finished */
3861 if ( ( rc = tls_send_finished ( tls ) ) != 0 ) {
3862 DBGC ( tls, "TLS %p could not send Finished: %s\n",
3863 tls, strerror ( rc ) );
3864 goto err;
3865 }
3866 tls->tx.pending &= ~TLS_TX_FINISHED;
3867 }
3868
3869 /* Reschedule process if pending transmissions remain,
3870 * otherwise send notification of a window change.
3871 */
3872 if ( tls->tx.pending ) {
3873 tls_tx_resume ( tls );
3874 } else {
3876 }
3877
3878 return;
3879
3880 err:
3881 tls_close ( tls, rc );
3882}
static int tls_send_certificate(struct tls_connection *tls)
Transmit Certificate record.
Definition tls.c:1360
static int tls_send_finished(struct tls_connection *tls)
Transmit Finished record.
Definition tls.c:1968
static int tls_send_client_hello(struct tls_connection *tls)
Transmit Client Hello record.
Definition tls.c:1349
static int tls_send_client_key_exchange(struct tls_connection *tls)
Transmit Client Key Exchange record.
Definition tls.c:1842
static int tls_send_change_cipher(struct tls_connection *tls)
Transmit Change Cipher record.
Definition tls.c:1951
static int tls_send_certificate_verify(struct tls_connection *tls)
Transmit Certificate Verify record.
Definition tls.c:1870

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

3902 {
3903 struct tls_session *session;
3904 char *name_copy;
3905 int rc;
3906
3907 /* Find existing matching session, if any */
3908 list_for_each_entry ( session, &tls_sessions, list ) {
3909 if ( ( strcmp ( name, session->name ) == 0 ) &&
3910 ( tls->server.root == session->root ) &&
3911 ( tls->client.key == session->key ) ) {
3912 ref_get ( &session->refcnt );
3913 tls->session = session;
3914 DBGC ( tls, "TLS %p joining session %s\n", tls, name );
3915 return 0;
3916 }
3917 }
3918
3919 /* Create new session */
3920 session = zalloc ( sizeof ( *session ) + strlen ( name )
3921 + 1 /* NUL */ );
3922 if ( ! session ) {
3923 rc = -ENOMEM;
3924 goto err_alloc;
3925 }
3926 ref_init ( &session->refcnt, free_tls_session );
3927 name_copy = ( ( ( void * ) session ) + sizeof ( *session ) );
3928 strcpy ( name_copy, name );
3929 session->name = name_copy;
3930 session->root = x509_root_get ( tls->server.root );
3931 session->key = privkey_get ( tls->client.key );
3932 INIT_LIST_HEAD ( &session->conn );
3933 list_add ( &session->list, &tls_sessions );
3934
3935 /* Record session */
3936 tls->session = session;
3937
3938 DBGC ( tls, "TLS %p created session %s\n", tls, name );
3939 return 0;
3940
3941 ref_put ( &session->refcnt );
3942 err_alloc:
3943 return rc;
3944}
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:359
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 3962 of file tls.c.

3963 {
3964 struct tls_connection *tls;
3965 int rc;
3966
3967 /* Allocate and initialise TLS structure */
3968 tls = malloc ( sizeof ( *tls ) );
3969 if ( ! tls ) {
3970 rc = -ENOMEM;
3971 goto err_alloc;
3972 }
3973 memset ( tls, 0, sizeof ( *tls ) );
3974 ref_init ( &tls->refcnt, free_tls );
3975 INIT_LIST_HEAD ( &tls->list );
3980 &tls->refcnt );
3981 tls->client.key = privkey_get ( key ? key : &private_key );
3983 tls->version = TLS_VERSION_MAX;
3984 tls_clear_cipher ( tls, &tls->tx.cipherspec.active );
3985 tls_clear_cipher ( tls, &tls->tx.cipherspec.pending );
3986 tls_clear_cipher ( tls, &tls->rx.cipherspec.active );
3987 tls_clear_cipher ( tls, &tls->rx.cipherspec.pending );
3988 tls_clear_handshake ( tls );
3989 tls->client.random.gmt_unix_time = time ( NULL );
3990 iob_populate ( &tls->rx.iobuf, &tls->rx.header, 0,
3991 sizeof ( tls->rx.header ) );
3992 INIT_LIST_HEAD ( &tls->rx.data );
3993 if ( ( rc = tls_generate_random ( tls, &tls->client.random.random,
3994 ( sizeof ( tls->client.random.random ) ) ) ) != 0 ) {
3995 goto err_random;
3996 }
3997 if ( ( rc = tls_session ( tls, name ) ) != 0 )
3998 goto err_session;
3999 list_add_tail ( &tls->list, &tls->session->conn );
4000
4001 /* Start negotiation */
4002 tls_restart ( tls );
4003
4004 /* Attach to parent interface, mortalise self, and return */
4005 intf_insert ( xfer, &tls->plainstream, &tls->cipherstream );
4006 ref_put ( &tls->refcnt );
4007 return 0;
4008
4009 err_session:
4010 err_random:
4011 ref_put ( &tls->refcnt );
4012 err_alloc:
4013 return rc;
4014}
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
uint32_t gmt_unix_time
GMT Unix time.
Definition tls.h:313
struct refcnt refcnt
Reference counter.
Definition tls.h:438
static struct interface_descriptor tls_cipherstream_desc
TLS ciphertext stream interface descriptor.
Definition tls.c:3686
static struct interface_descriptor tls_validator_desc
TLS certificate validator interface descriptor.
Definition tls.c:3760
static struct interface_descriptor tls_plainstream_desc
TLS plaintext stream interface descriptor.
Definition tls.c:3471
static void free_tls(struct refcnt *refcnt)
Free TLS connection.
Definition tls.c:383
static struct process_descriptor tls_process_desc
TLS TX process descriptor.
Definition tls.c:3885

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_client_random::gmt_unix_time, 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, NULL, 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:294
static void md5_sha1_final(void *ctx, void *out)
Generate MD5+SHA1 digest.
Definition tls.c:321
static void md5_sha1_update(void *ctx, const void *data, size_t len)
Accumulate data with MD5+SHA1 algorithm.
Definition tls.c:308

Hybrid MD5+SHA1 digest algorithm.

Definition at line 330 of file tls.c.

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

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

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

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

Null cipher suite.

Definition at line 851 of file tls.c.

851 {
853 .pubkey = &pubkey_null,
854 .cipher = &cipher_null,
855 .digest = &digest_null,
856};

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:1417

Public key exchange algorithm.

Definition at line 1486 of file tls.c.

1486 {
1487 .name = "pubkey",
1489};

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:1587

Ephemeral Diffie-Hellman key exchange algorithm.

Definition at line 1701 of file tls.c.

1701 {
1702 .name = "dhe",
1704};

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:1712

Ephemeral Elliptic Curve Diffie-Hellman key exchange algorithm.

Definition at line 1831 of file tls.c.

1831 {
1832 .name = "ecdhe",
1834};

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:3448
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:3420
static size_t tls_plainstream_window(struct tls_connection *tls)
Check flow control window.
Definition tls.c:3403
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 3460 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:3460

TLS plaintext stream interface descriptor.

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

TLS ciphertext stream interface operations.

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

TLS ciphertext stream interface descriptor.

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

TLS certificate validator interface operations.

Definition at line 3755 of file tls.c.

3755 {
3757};

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

TLS certificate validator interface descriptor.

Definition at line 3760 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:3776
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 3885 of file tls.c.

Referenced by add_tls().