mirror of https://github.com/ipxe/ipxe.git
[tls] Group client and server state in TLS connection structure
The TLS connection structure has grown to become unmanageably large as new features and support for new TLS protocol versions have been added over time. Split out the portions of struct tls_connection that are specific to client and server operations into separate structures, and simplify some structure field names. Signed-off-by: Michael Brown <mcb30@ipxe.org>pull/1171/head
parent
c9cac76a5c
commit
acbabdb335
|
@ -378,6 +378,38 @@ struct tls_rx {
|
||||||
struct io_buffer *handshake;
|
struct io_buffer *handshake;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** TLS client state */
|
||||||
|
struct tls_client {
|
||||||
|
/** Random bytes */
|
||||||
|
struct tls_client_random random;
|
||||||
|
/** Private key (if used) */
|
||||||
|
struct private_key *key;
|
||||||
|
/** Certificate chain (if used) */
|
||||||
|
struct x509_chain *chain;
|
||||||
|
/** Security negotiation pending operation */
|
||||||
|
struct pending_operation negotiation;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** TLS server state */
|
||||||
|
struct tls_server {
|
||||||
|
/** Random bytes */
|
||||||
|
uint8_t random[32];
|
||||||
|
/** Server Key Exchange record (if any) */
|
||||||
|
void *exchange;
|
||||||
|
/** Server Key Exchange record length */
|
||||||
|
size_t exchange_len;
|
||||||
|
/** Root of trust */
|
||||||
|
struct x509_root *root;
|
||||||
|
/** Certificate chain */
|
||||||
|
struct x509_chain *chain;
|
||||||
|
/** Certificate validator */
|
||||||
|
struct interface validator;
|
||||||
|
/** Certificate validation pending operation */
|
||||||
|
struct pending_operation validation;
|
||||||
|
/** Security negotiation pending operation */
|
||||||
|
struct pending_operation negotiation;
|
||||||
|
};
|
||||||
|
|
||||||
/** A TLS connection */
|
/** A TLS connection */
|
||||||
struct tls_connection {
|
struct tls_connection {
|
||||||
/** Reference counter */
|
/** Reference counter */
|
||||||
|
@ -405,45 +437,23 @@ struct tls_connection {
|
||||||
uint16_t version;
|
uint16_t version;
|
||||||
/** Master secret */
|
/** Master secret */
|
||||||
uint8_t master_secret[48];
|
uint8_t master_secret[48];
|
||||||
/** Server random bytes */
|
|
||||||
uint8_t server_random[32];
|
|
||||||
/** Client random bytes */
|
|
||||||
struct tls_client_random client_random;
|
|
||||||
/** Server Key Exchange record (if any) */
|
|
||||||
void *server_key;
|
|
||||||
/** Server Key Exchange record length */
|
|
||||||
size_t server_key_len;
|
|
||||||
/** Digest algorithm used for handshake verification */
|
/** Digest algorithm used for handshake verification */
|
||||||
struct digest_algorithm *handshake_digest;
|
struct digest_algorithm *handshake_digest;
|
||||||
/** Digest algorithm context used for handshake verification */
|
/** Digest algorithm context used for handshake verification */
|
||||||
uint8_t *handshake_ctx;
|
uint8_t *handshake_ctx;
|
||||||
/** Private key */
|
|
||||||
struct private_key *key;
|
|
||||||
/** Client certificate chain (if used) */
|
|
||||||
struct x509_chain *certs;
|
|
||||||
/** Secure renegotiation flag */
|
/** Secure renegotiation flag */
|
||||||
int secure_renegotiation;
|
int secure_renegotiation;
|
||||||
/** Verification data */
|
/** Verification data */
|
||||||
struct tls_verify_data verify;
|
struct tls_verify_data verify;
|
||||||
|
|
||||||
/** Root of trust */
|
|
||||||
struct x509_root *root;
|
|
||||||
/** Server certificate chain */
|
|
||||||
struct x509_chain *chain;
|
|
||||||
/** Certificate validator */
|
|
||||||
struct interface validator;
|
|
||||||
|
|
||||||
/** Client security negotiation pending operation */
|
|
||||||
struct pending_operation client_negotiation;
|
|
||||||
/** Server security negotiation pending operation */
|
|
||||||
struct pending_operation server_negotiation;
|
|
||||||
/** Certificate validation pending operation */
|
|
||||||
struct pending_operation validation;
|
|
||||||
|
|
||||||
/** Transmit state */
|
/** Transmit state */
|
||||||
struct tls_tx tx;
|
struct tls_tx tx;
|
||||||
/** Receive state */
|
/** Receive state */
|
||||||
struct tls_rx rx;
|
struct tls_rx rx;
|
||||||
|
/** Client state */
|
||||||
|
struct tls_client client;
|
||||||
|
/** Server state */
|
||||||
|
struct tls_server server;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** RX I/O buffer size
|
/** RX I/O buffer size
|
||||||
|
|
213
src/net/tls.c
213
src/net/tls.c
|
@ -251,8 +251,8 @@ static void tls_set_uint24 ( tls24_t *field24, unsigned long value ) {
|
||||||
* @ret is_ready TLS connection is ready
|
* @ret is_ready TLS connection is ready
|
||||||
*/
|
*/
|
||||||
static int tls_ready ( struct tls_connection *tls ) {
|
static int tls_ready ( struct tls_connection *tls ) {
|
||||||
return ( ( ! is_pending ( &tls->client_negotiation ) ) &&
|
return ( ( ! is_pending ( &tls->client.negotiation ) ) &&
|
||||||
( ! is_pending ( &tls->server_negotiation ) ) );
|
( ! is_pending ( &tls->server.negotiation ) ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -386,17 +386,17 @@ static void free_tls ( struct refcnt *refcnt ) {
|
||||||
tls_clear_cipher ( tls, &tls->tx.cipherspec.pending );
|
tls_clear_cipher ( tls, &tls->tx.cipherspec.pending );
|
||||||
tls_clear_cipher ( tls, &tls->rx.cipherspec.active );
|
tls_clear_cipher ( tls, &tls->rx.cipherspec.active );
|
||||||
tls_clear_cipher ( tls, &tls->rx.cipherspec.pending );
|
tls_clear_cipher ( tls, &tls->rx.cipherspec.pending );
|
||||||
free ( tls->server_key );
|
free ( tls->server.exchange );
|
||||||
free ( tls->handshake_ctx );
|
free ( tls->handshake_ctx );
|
||||||
list_for_each_entry_safe ( iobuf, tmp, &tls->rx.data, list ) {
|
list_for_each_entry_safe ( iobuf, tmp, &tls->rx.data, list ) {
|
||||||
list_del ( &iobuf->list );
|
list_del ( &iobuf->list );
|
||||||
free_iob ( iobuf );
|
free_iob ( iobuf );
|
||||||
}
|
}
|
||||||
free_iob ( tls->rx.handshake );
|
free_iob ( tls->rx.handshake );
|
||||||
x509_chain_put ( tls->certs );
|
privkey_put ( tls->client.key );
|
||||||
x509_chain_put ( tls->chain );
|
x509_chain_put ( tls->client.chain );
|
||||||
x509_root_put ( tls->root );
|
x509_chain_put ( tls->server.chain );
|
||||||
privkey_put ( tls->key );
|
x509_root_put ( tls->server.root );
|
||||||
|
|
||||||
/* Drop reference to session */
|
/* Drop reference to session */
|
||||||
assert ( list_empty ( &tls->list ) );
|
assert ( list_empty ( &tls->list ) );
|
||||||
|
@ -415,9 +415,9 @@ static void free_tls ( struct refcnt *refcnt ) {
|
||||||
static void tls_close ( struct tls_connection *tls, int rc ) {
|
static void tls_close ( struct tls_connection *tls, int rc ) {
|
||||||
|
|
||||||
/* Remove pending operations, if applicable */
|
/* Remove pending operations, if applicable */
|
||||||
pending_put ( &tls->client_negotiation );
|
pending_put ( &tls->client.negotiation );
|
||||||
pending_put ( &tls->server_negotiation );
|
pending_put ( &tls->server.negotiation );
|
||||||
pending_put ( &tls->validation );
|
pending_put ( &tls->server.validation );
|
||||||
|
|
||||||
/* Remove process */
|
/* Remove process */
|
||||||
process_del ( &tls->tx.process );
|
process_del ( &tls->tx.process );
|
||||||
|
@ -425,7 +425,7 @@ static void tls_close ( struct tls_connection *tls, int rc ) {
|
||||||
/* Close all interfaces */
|
/* Close all interfaces */
|
||||||
intf_shutdown ( &tls->cipherstream, rc );
|
intf_shutdown ( &tls->cipherstream, rc );
|
||||||
intf_shutdown ( &tls->plainstream, rc );
|
intf_shutdown ( &tls->plainstream, rc );
|
||||||
intf_shutdown ( &tls->validator, rc );
|
intf_shutdown ( &tls->server.validator, rc );
|
||||||
|
|
||||||
/* Remove from session */
|
/* Remove from session */
|
||||||
list_del ( &tls->list );
|
list_del ( &tls->list );
|
||||||
|
@ -640,15 +640,15 @@ static void tls_generate_master_secret ( struct tls_connection *tls,
|
||||||
DBGC ( tls, "TLS %p pre-master-secret:\n", tls );
|
DBGC ( tls, "TLS %p pre-master-secret:\n", tls );
|
||||||
DBGC_HD ( tls, pre_master_secret, pre_master_secret_len );
|
DBGC_HD ( tls, pre_master_secret, pre_master_secret_len );
|
||||||
DBGC ( tls, "TLS %p client random bytes:\n", tls );
|
DBGC ( tls, "TLS %p client random bytes:\n", tls );
|
||||||
DBGC_HD ( tls, &tls->client_random, sizeof ( tls->client_random ) );
|
DBGC_HD ( tls, &tls->client.random, sizeof ( tls->client.random ) );
|
||||||
DBGC ( tls, "TLS %p server random bytes:\n", tls );
|
DBGC ( tls, "TLS %p server random bytes:\n", tls );
|
||||||
DBGC_HD ( tls, &tls->server_random, sizeof ( tls->server_random ) );
|
DBGC_HD ( tls, &tls->server.random, sizeof ( tls->server.random ) );
|
||||||
|
|
||||||
tls_prf_label ( tls, pre_master_secret, pre_master_secret_len,
|
tls_prf_label ( tls, pre_master_secret, pre_master_secret_len,
|
||||||
&tls->master_secret, sizeof ( tls->master_secret ),
|
&tls->master_secret, sizeof ( tls->master_secret ),
|
||||||
"master secret",
|
"master secret",
|
||||||
&tls->client_random, sizeof ( tls->client_random ),
|
&tls->client.random, sizeof ( tls->client.random ),
|
||||||
&tls->server_random, sizeof ( tls->server_random ) );
|
&tls->server.random, sizeof ( tls->server.random ) );
|
||||||
|
|
||||||
DBGC ( tls, "TLS %p generated master secret:\n", tls );
|
DBGC ( tls, "TLS %p generated master secret:\n", tls );
|
||||||
DBGC_HD ( tls, &tls->master_secret, sizeof ( tls->master_secret ) );
|
DBGC_HD ( tls, &tls->master_secret, sizeof ( tls->master_secret ) );
|
||||||
|
@ -675,8 +675,8 @@ static int tls_generate_keys ( struct tls_connection *tls ) {
|
||||||
/* Generate key block */
|
/* Generate key block */
|
||||||
tls_prf_label ( tls, &tls->master_secret, sizeof ( tls->master_secret ),
|
tls_prf_label ( tls, &tls->master_secret, sizeof ( tls->master_secret ),
|
||||||
key_block, sizeof ( key_block ), "key expansion",
|
key_block, sizeof ( key_block ), "key expansion",
|
||||||
&tls->server_random, sizeof ( tls->server_random ),
|
&tls->server.random, sizeof ( tls->server.random ),
|
||||||
&tls->client_random, sizeof ( tls->client_random ) );
|
&tls->client.random, sizeof ( tls->client.random ) );
|
||||||
|
|
||||||
/* Split key block into portions */
|
/* Split key block into portions */
|
||||||
key = key_block;
|
key = key_block;
|
||||||
|
@ -1110,15 +1110,15 @@ static void tls_restart ( struct tls_connection *tls ) {
|
||||||
|
|
||||||
/* Sanity check */
|
/* Sanity check */
|
||||||
assert ( ! tls->tx.pending );
|
assert ( ! tls->tx.pending );
|
||||||
assert ( ! is_pending ( &tls->client_negotiation ) );
|
assert ( ! is_pending ( &tls->client.negotiation ) );
|
||||||
assert ( ! is_pending ( &tls->server_negotiation ) );
|
assert ( ! is_pending ( &tls->server.negotiation ) );
|
||||||
assert ( ! is_pending ( &tls->validation ) );
|
assert ( ! is_pending ( &tls->server.validation ) );
|
||||||
|
|
||||||
/* (Re)start negotiation */
|
/* (Re)start negotiation */
|
||||||
tls->tx.pending = TLS_TX_CLIENT_HELLO;
|
tls->tx.pending = TLS_TX_CLIENT_HELLO;
|
||||||
tls_tx_resume ( tls );
|
tls_tx_resume ( tls );
|
||||||
pending_get ( &tls->client_negotiation );
|
pending_get ( &tls->client.negotiation );
|
||||||
pending_get ( &tls->server_negotiation );
|
pending_get ( &tls->server.negotiation );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1237,7 +1237,7 @@ static int tls_client_hello ( struct tls_connection *tls,
|
||||||
htonl ( sizeof ( hello ) -
|
htonl ( sizeof ( hello ) -
|
||||||
sizeof ( hello.type_length ) ) );
|
sizeof ( hello.type_length ) ) );
|
||||||
hello.version = htons ( TLS_VERSION_MAX );
|
hello.version = htons ( TLS_VERSION_MAX );
|
||||||
memcpy ( &hello.random, &tls->client_random, sizeof ( hello.random ) );
|
memcpy ( &hello.random, &tls->client.random, sizeof ( hello.random ) );
|
||||||
hello.session_id_len = tls->session_id_len;
|
hello.session_id_len = tls->session_id_len;
|
||||||
memcpy ( hello.session_id, tls->session_id,
|
memcpy ( hello.session_id, tls->session_id,
|
||||||
sizeof ( hello.session_id ) );
|
sizeof ( hello.session_id ) );
|
||||||
|
@ -1344,7 +1344,7 @@ static int tls_send_certificate ( struct tls_connection *tls ) {
|
||||||
|
|
||||||
/* Calculate length of client certificates */
|
/* Calculate length of client certificates */
|
||||||
len = 0;
|
len = 0;
|
||||||
list_for_each_entry ( link, &tls->certs->links, list ) {
|
list_for_each_entry ( link, &tls->client.chain->links, list ) {
|
||||||
cert = link->cert;
|
cert = link->cert;
|
||||||
len += ( sizeof ( *certificate ) + cert->raw.len );
|
len += ( sizeof ( *certificate ) + cert->raw.len );
|
||||||
DBGC ( tls, "TLS %p sending client certificate %s\n",
|
DBGC ( tls, "TLS %p sending client certificate %s\n",
|
||||||
|
@ -1365,7 +1365,7 @@ static int tls_send_certificate ( struct tls_connection *tls ) {
|
||||||
sizeof ( certificates->type_length ) ) );
|
sizeof ( certificates->type_length ) ) );
|
||||||
tls_set_uint24 ( &certificates->length, len );
|
tls_set_uint24 ( &certificates->length, len );
|
||||||
certificate = &certificates->certificates[0];
|
certificate = &certificates->certificates[0];
|
||||||
list_for_each_entry ( link, &tls->certs->links, list ) {
|
list_for_each_entry ( link, &tls->client.chain->links, list ) {
|
||||||
cert = link->cert;
|
cert = link->cert;
|
||||||
tls_set_uint24 ( &certificate->length, cert->raw.len );
|
tls_set_uint24 ( &certificate->length, cert->raw.len );
|
||||||
memcpy ( certificate->data, cert->raw.data, cert->raw.len );
|
memcpy ( certificate->data, cert->raw.data, cert->raw.len );
|
||||||
|
@ -1470,9 +1470,9 @@ static int tls_verify_dh_params ( struct tls_connection *tls,
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
/* Signature follows parameters */
|
/* Signature follows parameters */
|
||||||
assert ( param_len <= tls->server_key_len );
|
assert ( param_len <= tls->server.exchange_len );
|
||||||
data = ( tls->server_key + param_len );
|
data = ( tls->server.exchange + param_len );
|
||||||
remaining = ( tls->server_key_len - param_len );
|
remaining = ( tls->server.exchange_len - param_len );
|
||||||
|
|
||||||
/* Parse signature from ServerKeyExchange */
|
/* Parse signature from ServerKeyExchange */
|
||||||
sig = data;
|
sig = data;
|
||||||
|
@ -1481,7 +1481,8 @@ static int tls_verify_dh_params ( struct tls_connection *tls,
|
||||||
sizeof ( *sig ) ) ) ) {
|
sizeof ( *sig ) ) ) ) {
|
||||||
DBGC ( tls, "TLS %p received underlength ServerKeyExchange\n",
|
DBGC ( tls, "TLS %p received underlength ServerKeyExchange\n",
|
||||||
tls );
|
tls );
|
||||||
DBGC_HDA ( tls, 0, tls->server_key, tls->server_key_len );
|
DBGC_HDA ( tls, 0, tls->server.exchange,
|
||||||
|
tls->server.exchange_len );
|
||||||
return -EINVAL_KEY_EXCHANGE;
|
return -EINVAL_KEY_EXCHANGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1514,11 +1515,11 @@ static int tls_verify_dh_params ( struct tls_connection *tls,
|
||||||
|
|
||||||
/* Calculate digest */
|
/* Calculate digest */
|
||||||
digest_init ( digest, ctx );
|
digest_init ( digest, ctx );
|
||||||
digest_update ( digest, ctx, &tls->client_random,
|
digest_update ( digest, ctx, &tls->client.random,
|
||||||
sizeof ( tls->client_random ) );
|
sizeof ( tls->client.random ) );
|
||||||
digest_update ( digest, ctx, tls->server_random,
|
digest_update ( digest, ctx, tls->server.random,
|
||||||
sizeof ( tls->server_random ) );
|
sizeof ( tls->server.random ) );
|
||||||
digest_update ( digest, ctx, tls->server_key, param_len );
|
digest_update ( digest, ctx, tls->server.exchange, param_len );
|
||||||
digest_final ( digest, ctx, hash );
|
digest_final ( digest, ctx, hash );
|
||||||
|
|
||||||
/* Verify signature */
|
/* Verify signature */
|
||||||
|
@ -1527,8 +1528,8 @@ static int tls_verify_dh_params ( struct tls_connection *tls,
|
||||||
signature_len ) ) != 0 ) {
|
signature_len ) ) != 0 ) {
|
||||||
DBGC ( tls, "TLS %p ServerKeyExchange failed "
|
DBGC ( tls, "TLS %p ServerKeyExchange failed "
|
||||||
"verification\n", tls );
|
"verification\n", tls );
|
||||||
DBGC_HDA ( tls, 0, tls->server_key,
|
DBGC_HDA ( tls, 0, tls->server.exchange,
|
||||||
tls->server_key_len );
|
tls->server.exchange_len );
|
||||||
return -EPERM_KEY_EXCHANGE;
|
return -EPERM_KEY_EXCHANGE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1543,7 +1544,7 @@ static int tls_verify_dh_params ( struct tls_connection *tls,
|
||||||
* @ret rc Return status code
|
* @ret rc Return status code
|
||||||
*/
|
*/
|
||||||
static int tls_send_client_key_exchange_dhe ( struct tls_connection *tls ) {
|
static int tls_send_client_key_exchange_dhe ( struct tls_connection *tls ) {
|
||||||
uint8_t private[ sizeof ( tls->client_random.random ) ];
|
uint8_t private[ sizeof ( tls->client.random.random ) ];
|
||||||
const struct {
|
const struct {
|
||||||
uint16_t len;
|
uint16_t len;
|
||||||
uint8_t data[0];
|
uint8_t data[0];
|
||||||
|
@ -1556,8 +1557,8 @@ static int tls_send_client_key_exchange_dhe ( struct tls_connection *tls ) {
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
/* Parse ServerKeyExchange */
|
/* Parse ServerKeyExchange */
|
||||||
data = tls->server_key;
|
data = tls->server.exchange;
|
||||||
remaining = tls->server_key_len;
|
remaining = tls->server.exchange_len;
|
||||||
for ( i = 0 ; i < ( sizeof ( dh_val ) / sizeof ( dh_val[0] ) ) ; i++ ){
|
for ( i = 0 ; i < ( sizeof ( dh_val ) / sizeof ( dh_val[0] ) ) ; i++ ){
|
||||||
dh_val[i] = data;
|
dh_val[i] = data;
|
||||||
if ( ( sizeof ( *dh_val[i] ) > remaining ) ||
|
if ( ( sizeof ( *dh_val[i] ) > remaining ) ||
|
||||||
|
@ -1565,8 +1566,8 @@ static int tls_send_client_key_exchange_dhe ( struct tls_connection *tls ) {
|
||||||
sizeof ( *dh_val[i] ) ) )){
|
sizeof ( *dh_val[i] ) ) )){
|
||||||
DBGC ( tls, "TLS %p received underlength "
|
DBGC ( tls, "TLS %p received underlength "
|
||||||
"ServerKeyExchange\n", tls );
|
"ServerKeyExchange\n", tls );
|
||||||
DBGC_HDA ( tls, 0, tls->server_key,
|
DBGC_HDA ( tls, 0, tls->server.exchange,
|
||||||
tls->server_key_len );
|
tls->server.exchange_len );
|
||||||
rc = -EINVAL_KEY_EXCHANGE;
|
rc = -EINVAL_KEY_EXCHANGE;
|
||||||
goto err_header;
|
goto err_header;
|
||||||
}
|
}
|
||||||
|
@ -1574,7 +1575,7 @@ static int tls_send_client_key_exchange_dhe ( struct tls_connection *tls ) {
|
||||||
data += frag_len;
|
data += frag_len;
|
||||||
remaining -= frag_len;
|
remaining -= frag_len;
|
||||||
}
|
}
|
||||||
param_len = ( tls->server_key_len - remaining );
|
param_len = ( tls->server.exchange_len - remaining );
|
||||||
|
|
||||||
/* Verify parameter signature */
|
/* Verify parameter signature */
|
||||||
if ( ( rc = tls_verify_dh_params ( tls, param_len ) ) != 0 )
|
if ( ( rc = tls_verify_dh_params ( tls, param_len ) ) != 0 )
|
||||||
|
@ -1679,12 +1680,14 @@ static int tls_send_client_key_exchange_ecdhe ( struct tls_connection *tls ) {
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
/* Parse ServerKeyExchange record */
|
/* Parse ServerKeyExchange record */
|
||||||
ecdh = tls->server_key;
|
ecdh = tls->server.exchange;
|
||||||
if ( ( sizeof ( *ecdh ) > tls->server_key_len ) ||
|
if ( ( sizeof ( *ecdh ) > tls->server.exchange_len ) ||
|
||||||
( ecdh->public_len > ( tls->server_key_len - sizeof ( *ecdh ) ))){
|
( ecdh->public_len > ( tls->server.exchange_len -
|
||||||
|
sizeof ( *ecdh ) ) ) ) {
|
||||||
DBGC ( tls, "TLS %p received underlength ServerKeyExchange\n",
|
DBGC ( tls, "TLS %p received underlength ServerKeyExchange\n",
|
||||||
tls );
|
tls );
|
||||||
DBGC_HDA ( tls, 0, tls->server_key, tls->server_key_len );
|
DBGC_HDA ( tls, 0, tls->server.exchange,
|
||||||
|
tls->server.exchange_len );
|
||||||
return -EINVAL_KEY_EXCHANGE;
|
return -EINVAL_KEY_EXCHANGE;
|
||||||
}
|
}
|
||||||
param_len = ( sizeof ( *ecdh ) + ecdh->public_len );
|
param_len = ( sizeof ( *ecdh ) + ecdh->public_len );
|
||||||
|
@ -1697,14 +1700,16 @@ static int tls_send_client_key_exchange_ecdhe ( struct tls_connection *tls ) {
|
||||||
if ( ecdh->curve_type != TLS_NAMED_CURVE_TYPE ) {
|
if ( ecdh->curve_type != TLS_NAMED_CURVE_TYPE ) {
|
||||||
DBGC ( tls, "TLS %p unsupported curve type %d\n",
|
DBGC ( tls, "TLS %p unsupported curve type %d\n",
|
||||||
tls, ecdh->curve_type );
|
tls, ecdh->curve_type );
|
||||||
DBGC_HDA ( tls, 0, tls->server_key, tls->server_key_len );
|
DBGC_HDA ( tls, 0, tls->server.exchange,
|
||||||
|
tls->server.exchange_len );
|
||||||
return -ENOTSUP_CURVE;
|
return -ENOTSUP_CURVE;
|
||||||
}
|
}
|
||||||
curve = tls_find_named_curve ( ecdh->named_curve );
|
curve = tls_find_named_curve ( ecdh->named_curve );
|
||||||
if ( ! curve ) {
|
if ( ! curve ) {
|
||||||
DBGC ( tls, "TLS %p unsupported named curve %d\n",
|
DBGC ( tls, "TLS %p unsupported named curve %d\n",
|
||||||
tls, ntohs ( ecdh->named_curve ) );
|
tls, ntohs ( ecdh->named_curve ) );
|
||||||
DBGC_HDA ( tls, 0, tls->server_key, tls->server_key_len );
|
DBGC_HDA ( tls, 0, tls->server.exchange,
|
||||||
|
tls->server.exchange_len );
|
||||||
return -ENOTSUP_CURVE;
|
return -ENOTSUP_CURVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1712,7 +1717,8 @@ static int tls_send_client_key_exchange_ecdhe ( struct tls_connection *tls ) {
|
||||||
if ( ecdh->public_len != curve->curve->keysize ) {
|
if ( ecdh->public_len != curve->curve->keysize ) {
|
||||||
DBGC ( tls, "TLS %p invalid %s key\n",
|
DBGC ( tls, "TLS %p invalid %s key\n",
|
||||||
tls, curve->curve->name );
|
tls, curve->curve->name );
|
||||||
DBGC_HDA ( tls, 0, tls->server_key, tls->server_key_len );
|
DBGC_HDA ( tls, 0, tls->server.exchange,
|
||||||
|
tls->server.exchange_len );
|
||||||
return -EINVAL_KEY_EXCHANGE;
|
return -EINVAL_KEY_EXCHANGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1810,9 +1816,9 @@ static int tls_send_client_key_exchange ( struct tls_connection *tls ) {
|
||||||
*/
|
*/
|
||||||
static int tls_send_certificate_verify ( struct tls_connection *tls ) {
|
static int tls_send_certificate_verify ( struct tls_connection *tls ) {
|
||||||
struct digest_algorithm *digest = tls->handshake_digest;
|
struct digest_algorithm *digest = tls->handshake_digest;
|
||||||
struct x509_certificate *cert = x509_first ( tls->certs );
|
struct x509_certificate *cert = x509_first ( tls->client.chain );
|
||||||
struct pubkey_algorithm *pubkey = cert->signature_algorithm->pubkey;
|
struct pubkey_algorithm *pubkey = cert->signature_algorithm->pubkey;
|
||||||
struct asn1_cursor *key = privkey_cursor ( tls->key );
|
struct asn1_cursor *key = privkey_cursor ( tls->client.key );
|
||||||
uint8_t digest_out[ digest->digestsize ];
|
uint8_t digest_out[ digest->digestsize ];
|
||||||
uint8_t ctx[ pubkey->ctxsize ];
|
uint8_t ctx[ pubkey->ctxsize ];
|
||||||
struct tls_signature_hash_algorithm *sig_hash = NULL;
|
struct tls_signature_hash_algorithm *sig_hash = NULL;
|
||||||
|
@ -1944,7 +1950,7 @@ static int tls_send_finished ( struct tls_connection *tls ) {
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
/* Mark client as finished */
|
/* Mark client as finished */
|
||||||
pending_put ( &tls->client_negotiation );
|
pending_put ( &tls->client.negotiation );
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -2185,8 +2191,8 @@ static int tls_new_server_hello ( struct tls_connection *tls,
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
/* Copy out server random bytes */
|
/* Copy out server random bytes */
|
||||||
memcpy ( &tls->server_random, &hello_a->random,
|
memcpy ( &tls->server.random, &hello_a->random,
|
||||||
sizeof ( tls->server_random ) );
|
sizeof ( tls->server.random ) );
|
||||||
|
|
||||||
/* Check session ID */
|
/* Check session ID */
|
||||||
if ( hello_a->session_id_len &&
|
if ( hello_a->session_id_len &&
|
||||||
|
@ -2306,12 +2312,12 @@ static int tls_parse_chain ( struct tls_connection *tls,
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
/* Free any existing certificate chain */
|
/* Free any existing certificate chain */
|
||||||
x509_chain_put ( tls->chain );
|
x509_chain_put ( tls->server.chain );
|
||||||
tls->chain = NULL;
|
tls->server.chain = NULL;
|
||||||
|
|
||||||
/* Create certificate chain */
|
/* Create certificate chain */
|
||||||
tls->chain = x509_alloc_chain();
|
tls->server.chain = x509_alloc_chain();
|
||||||
if ( ! tls->chain ) {
|
if ( ! tls->server.chain ) {
|
||||||
rc = -ENOMEM_CHAIN;
|
rc = -ENOMEM_CHAIN;
|
||||||
goto err_alloc_chain;
|
goto err_alloc_chain;
|
||||||
}
|
}
|
||||||
|
@ -2343,14 +2349,15 @@ static int tls_parse_chain ( struct tls_connection *tls,
|
||||||
record_len = ( sizeof ( *certificate ) + certificate_len );
|
record_len = ( sizeof ( *certificate ) + certificate_len );
|
||||||
|
|
||||||
/* Add certificate to chain */
|
/* Add certificate to chain */
|
||||||
if ( ( rc = x509_append_raw ( tls->chain, certificate->data,
|
if ( ( rc = x509_append_raw ( tls->server.chain,
|
||||||
|
certificate->data,
|
||||||
certificate_len ) ) != 0 ) {
|
certificate_len ) ) != 0 ) {
|
||||||
DBGC ( tls, "TLS %p could not append certificate: %s\n",
|
DBGC ( tls, "TLS %p could not append certificate: %s\n",
|
||||||
tls, strerror ( rc ) );
|
tls, strerror ( rc ) );
|
||||||
DBGC_HDA ( tls, 0, data, remaining );
|
DBGC_HDA ( tls, 0, data, remaining );
|
||||||
goto err_parse;
|
goto err_parse;
|
||||||
}
|
}
|
||||||
cert = x509_last ( tls->chain );
|
cert = x509_last ( tls->server.chain );
|
||||||
DBGC ( tls, "TLS %p found certificate %s\n",
|
DBGC ( tls, "TLS %p found certificate %s\n",
|
||||||
tls, x509_name ( cert ) );
|
tls, x509_name ( cert ) );
|
||||||
|
|
||||||
|
@ -2364,8 +2371,8 @@ static int tls_parse_chain ( struct tls_connection *tls,
|
||||||
err_parse:
|
err_parse:
|
||||||
err_overlength:
|
err_overlength:
|
||||||
err_underlength:
|
err_underlength:
|
||||||
x509_chain_put ( tls->chain );
|
x509_chain_put ( tls->server.chain );
|
||||||
tls->chain = NULL;
|
tls->server.chain = NULL;
|
||||||
err_alloc_chain:
|
err_alloc_chain:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -2422,12 +2429,12 @@ static int tls_new_server_key_exchange ( struct tls_connection *tls,
|
||||||
const void *data, size_t len ) {
|
const void *data, size_t len ) {
|
||||||
|
|
||||||
/* Free any existing server key exchange record */
|
/* Free any existing server key exchange record */
|
||||||
free ( tls->server_key );
|
free ( tls->server.exchange );
|
||||||
tls->server_key_len = 0;
|
tls->server.exchange_len = 0;
|
||||||
|
|
||||||
/* Allocate copy of server key exchange record */
|
/* Allocate copy of server key exchange record */
|
||||||
tls->server_key = malloc ( len );
|
tls->server.exchange = malloc ( len );
|
||||||
if ( ! tls->server_key )
|
if ( ! tls->server.exchange )
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
/* Store copy of server key exchange record for later
|
/* Store copy of server key exchange record for later
|
||||||
|
@ -2435,8 +2442,8 @@ static int tls_new_server_key_exchange ( struct tls_connection *tls,
|
||||||
* since the certificate validation will not yet have
|
* since the certificate validation will not yet have
|
||||||
* completed.
|
* completed.
|
||||||
*/
|
*/
|
||||||
memcpy ( tls->server_key, data, len );
|
memcpy ( tls->server.exchange, data, len );
|
||||||
tls->server_key_len = len;
|
tls->server.exchange_len = len;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -2460,11 +2467,11 @@ static int tls_new_certificate_request ( struct tls_connection *tls,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Free any existing client certificate chain */
|
/* Free any existing client certificate chain */
|
||||||
x509_chain_put ( tls->certs );
|
x509_chain_put ( tls->client.chain );
|
||||||
tls->certs = NULL;
|
tls->client.chain = NULL;
|
||||||
|
|
||||||
/* Determine client certificate to be sent */
|
/* Determine client certificate to be sent */
|
||||||
cert = x509_find_key ( NULL, tls->key );
|
cert = x509_find_key ( NULL, tls->client.key );
|
||||||
if ( ! cert ) {
|
if ( ! cert ) {
|
||||||
DBGC ( tls, "TLS %p could not find certificate corresponding "
|
DBGC ( tls, "TLS %p could not find certificate corresponding "
|
||||||
"to private key\n", tls );
|
"to private key\n", tls );
|
||||||
|
@ -2476,18 +2483,18 @@ static int tls_new_certificate_request ( struct tls_connection *tls,
|
||||||
tls, x509_name ( cert ) );
|
tls, x509_name ( cert ) );
|
||||||
|
|
||||||
/* Create client certificate chain */
|
/* Create client certificate chain */
|
||||||
tls->certs = x509_alloc_chain();
|
tls->client.chain = x509_alloc_chain();
|
||||||
if ( ! tls->certs ) {
|
if ( ! tls->client.chain ) {
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
goto err_alloc;
|
goto err_alloc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Append client certificate to chain */
|
/* Append client certificate to chain */
|
||||||
if ( ( rc = x509_append ( tls->certs, cert ) ) != 0 )
|
if ( ( rc = x509_append ( tls->client.chain, cert ) ) != 0 )
|
||||||
goto err_append;
|
goto err_append;
|
||||||
|
|
||||||
/* Append any relevant issuer certificates */
|
/* Append any relevant issuer certificates */
|
||||||
if ( ( rc = x509_auto_append ( tls->certs, &certstore ) ) != 0 )
|
if ( ( rc = x509_auto_append ( tls->client.chain, &certstore ) ) != 0 )
|
||||||
goto err_auto_append;
|
goto err_auto_append;
|
||||||
|
|
||||||
/* Drop local reference to client certificate */
|
/* Drop local reference to client certificate */
|
||||||
|
@ -2497,8 +2504,8 @@ static int tls_new_certificate_request ( struct tls_connection *tls,
|
||||||
|
|
||||||
err_auto_append:
|
err_auto_append:
|
||||||
err_append:
|
err_append:
|
||||||
x509_chain_put ( tls->certs );
|
x509_chain_put ( tls->client.chain );
|
||||||
tls->certs = NULL;
|
tls->client.chain = NULL;
|
||||||
err_alloc:
|
err_alloc:
|
||||||
x509_put ( cert );
|
x509_put ( cert );
|
||||||
err_find:
|
err_find:
|
||||||
|
@ -2529,13 +2536,14 @@ static int tls_new_server_hello_done ( struct tls_connection *tls,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Begin certificate validation */
|
/* Begin certificate validation */
|
||||||
if ( ( rc = create_validator ( &tls->validator, tls->chain,
|
if ( ( rc = create_validator ( &tls->server.validator,
|
||||||
tls->root ) ) != 0 ) {
|
tls->server.chain,
|
||||||
|
tls->server.root ) ) != 0 ) {
|
||||||
DBGC ( tls, "TLS %p could not start certificate validation: "
|
DBGC ( tls, "TLS %p could not start certificate validation: "
|
||||||
"%s\n", tls, strerror ( rc ) );
|
"%s\n", tls, strerror ( rc ) );
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
pending_get ( &tls->validation );
|
pending_get ( &tls->server.validation );
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -2577,13 +2585,13 @@ static int tls_new_finished ( struct tls_connection *tls,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Mark server as finished */
|
/* Mark server as finished */
|
||||||
pending_put ( &tls->server_negotiation );
|
pending_put ( &tls->server.negotiation );
|
||||||
|
|
||||||
/* If we are resuming a session (i.e. if the server Finished
|
/* If we are resuming a session (i.e. if the server Finished
|
||||||
* arrives before the client Finished is sent), then schedule
|
* arrives before the client Finished is sent), then schedule
|
||||||
* transmission of Change Cipher and Finished.
|
* transmission of Change Cipher and Finished.
|
||||||
*/
|
*/
|
||||||
if ( is_pending ( &tls->client_negotiation ) ) {
|
if ( is_pending ( &tls->client.negotiation ) ) {
|
||||||
tls->tx.pending |= ( TLS_TX_CHANGE_CIPHER | TLS_TX_FINISHED );
|
tls->tx.pending |= ( TLS_TX_CHANGE_CIPHER | TLS_TX_FINISHED );
|
||||||
tls_tx_resume ( tls );
|
tls_tx_resume ( tls );
|
||||||
}
|
}
|
||||||
|
@ -3295,8 +3303,8 @@ static int tls_progress ( struct tls_connection *tls,
|
||||||
struct job_progress *progress ) {
|
struct job_progress *progress ) {
|
||||||
|
|
||||||
/* Return cipherstream or validator progress as applicable */
|
/* Return cipherstream or validator progress as applicable */
|
||||||
if ( is_pending ( &tls->validation ) ) {
|
if ( is_pending ( &tls->server.validation ) ) {
|
||||||
return job_progress ( &tls->validator, progress );
|
return job_progress ( &tls->server.validator, progress );
|
||||||
} else {
|
} else {
|
||||||
return job_progress ( &tls->cipherstream, progress );
|
return job_progress ( &tls->cipherstream, progress );
|
||||||
}
|
}
|
||||||
|
@ -3552,10 +3560,10 @@ static void tls_validator_done ( struct tls_connection *tls, int rc ) {
|
||||||
struct x509_certificate *cert;
|
struct x509_certificate *cert;
|
||||||
|
|
||||||
/* Mark validation as complete */
|
/* Mark validation as complete */
|
||||||
pending_put ( &tls->validation );
|
pending_put ( &tls->server.validation );
|
||||||
|
|
||||||
/* Close validator interface */
|
/* Close validator interface */
|
||||||
intf_restart ( &tls->validator, rc );
|
intf_restart ( &tls->server.validator, rc );
|
||||||
|
|
||||||
/* Check for validation failure */
|
/* Check for validation failure */
|
||||||
if ( rc != 0 ) {
|
if ( rc != 0 ) {
|
||||||
|
@ -3566,7 +3574,7 @@ static void tls_validator_done ( struct tls_connection *tls, int rc ) {
|
||||||
DBGC ( tls, "TLS %p certificate validation succeeded\n", tls );
|
DBGC ( tls, "TLS %p certificate validation succeeded\n", tls );
|
||||||
|
|
||||||
/* Extract first certificate */
|
/* Extract first certificate */
|
||||||
cert = x509_first ( tls->chain );
|
cert = x509_first ( tls->server.chain );
|
||||||
assert ( cert != NULL );
|
assert ( cert != NULL );
|
||||||
|
|
||||||
/* Verify server name */
|
/* Verify server name */
|
||||||
|
@ -3588,7 +3596,7 @@ static void tls_validator_done ( struct tls_connection *tls, int rc ) {
|
||||||
tls->tx.pending |= ( TLS_TX_CLIENT_KEY_EXCHANGE |
|
tls->tx.pending |= ( TLS_TX_CLIENT_KEY_EXCHANGE |
|
||||||
TLS_TX_CHANGE_CIPHER |
|
TLS_TX_CHANGE_CIPHER |
|
||||||
TLS_TX_FINISHED );
|
TLS_TX_FINISHED );
|
||||||
if ( tls->certs ) {
|
if ( tls->client.chain ) {
|
||||||
tls->tx.pending |= ( TLS_TX_CERTIFICATE |
|
tls->tx.pending |= ( TLS_TX_CERTIFICATE |
|
||||||
TLS_TX_CERTIFICATE_VERIFY );
|
TLS_TX_CERTIFICATE_VERIFY );
|
||||||
}
|
}
|
||||||
|
@ -3608,7 +3616,8 @@ static struct interface_operation tls_validator_ops[] = {
|
||||||
|
|
||||||
/** TLS certificate validator interface descriptor */
|
/** TLS certificate validator interface descriptor */
|
||||||
static struct interface_descriptor tls_validator_desc =
|
static struct interface_descriptor tls_validator_desc =
|
||||||
INTF_DESC ( struct tls_connection, validator, tls_validator_ops );
|
INTF_DESC ( struct tls_connection, server.validator,
|
||||||
|
tls_validator_ops );
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
*
|
*
|
||||||
|
@ -3640,7 +3649,7 @@ static void tls_tx_step ( struct tls_connection *tls ) {
|
||||||
list_for_each_entry ( conn, &session->conn, list ) {
|
list_for_each_entry ( conn, &session->conn, list ) {
|
||||||
if ( conn == tls )
|
if ( conn == tls )
|
||||||
break;
|
break;
|
||||||
if ( is_pending ( &conn->server_negotiation ) )
|
if ( is_pending ( &conn->server.negotiation ) )
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* Record or generate session ID and associated master secret */
|
/* Record or generate session ID and associated master secret */
|
||||||
|
@ -3654,8 +3663,8 @@ static void tls_tx_step ( struct tls_connection *tls ) {
|
||||||
} else {
|
} else {
|
||||||
/* No existing session: use a random session ID */
|
/* No existing session: use a random session ID */
|
||||||
assert ( sizeof ( tls->session_id ) ==
|
assert ( sizeof ( tls->session_id ) ==
|
||||||
sizeof ( tls->client_random ) );
|
sizeof ( tls->client.random ) );
|
||||||
memcpy ( tls->session_id, &tls->client_random,
|
memcpy ( tls->session_id, &tls->client.random,
|
||||||
sizeof ( tls->session_id ) );
|
sizeof ( tls->session_id ) );
|
||||||
tls->session_id_len = sizeof ( tls->session_id );
|
tls->session_id_len = sizeof ( tls->session_id );
|
||||||
}
|
}
|
||||||
|
@ -3756,8 +3765,8 @@ static int tls_session ( struct tls_connection *tls, const char *name ) {
|
||||||
/* Find existing matching session, if any */
|
/* Find existing matching session, if any */
|
||||||
list_for_each_entry ( session, &tls_sessions, list ) {
|
list_for_each_entry ( session, &tls_sessions, list ) {
|
||||||
if ( ( strcmp ( name, session->name ) == 0 ) &&
|
if ( ( strcmp ( name, session->name ) == 0 ) &&
|
||||||
( tls->root == session->root ) &&
|
( tls->server.root == session->root ) &&
|
||||||
( tls->key == session->key ) ) {
|
( tls->client.key == session->key ) ) {
|
||||||
ref_get ( &session->refcnt );
|
ref_get ( &session->refcnt );
|
||||||
tls->session = session;
|
tls->session = session;
|
||||||
DBGC ( tls, "TLS %p joining session %s\n", tls, name );
|
DBGC ( tls, "TLS %p joining session %s\n", tls, name );
|
||||||
|
@ -3776,8 +3785,8 @@ static int tls_session ( struct tls_connection *tls, const char *name ) {
|
||||||
name_copy = ( ( ( void * ) session ) + sizeof ( *session ) );
|
name_copy = ( ( ( void * ) session ) + sizeof ( *session ) );
|
||||||
strcpy ( name_copy, name );
|
strcpy ( name_copy, name );
|
||||||
session->name = name_copy;
|
session->name = name_copy;
|
||||||
session->root = x509_root_get ( tls->root );
|
session->root = x509_root_get ( tls->server.root );
|
||||||
session->key = privkey_get ( tls->key );
|
session->key = privkey_get ( tls->client.key );
|
||||||
INIT_LIST_HEAD ( &session->conn );
|
INIT_LIST_HEAD ( &session->conn );
|
||||||
list_add ( &session->list, &tls_sessions );
|
list_add ( &session->list, &tls_sessions );
|
||||||
|
|
||||||
|
@ -3824,23 +3833,23 @@ int add_tls ( struct interface *xfer, const char *name,
|
||||||
INIT_LIST_HEAD ( &tls->list );
|
INIT_LIST_HEAD ( &tls->list );
|
||||||
intf_init ( &tls->plainstream, &tls_plainstream_desc, &tls->refcnt );
|
intf_init ( &tls->plainstream, &tls_plainstream_desc, &tls->refcnt );
|
||||||
intf_init ( &tls->cipherstream, &tls_cipherstream_desc, &tls->refcnt );
|
intf_init ( &tls->cipherstream, &tls_cipherstream_desc, &tls->refcnt );
|
||||||
intf_init ( &tls->validator, &tls_validator_desc, &tls->refcnt );
|
intf_init ( &tls->server.validator, &tls_validator_desc, &tls->refcnt );
|
||||||
process_init_stopped ( &tls->tx.process, &tls_process_desc,
|
process_init_stopped ( &tls->tx.process, &tls_process_desc,
|
||||||
&tls->refcnt );
|
&tls->refcnt );
|
||||||
tls->key = privkey_get ( key ? key : &private_key );
|
tls->client.key = privkey_get ( key ? key : &private_key );
|
||||||
tls->root = x509_root_get ( root ? root : &root_certificates );
|
tls->server.root = x509_root_get ( root ? root : &root_certificates );
|
||||||
tls->version = TLS_VERSION_MAX;
|
tls->version = TLS_VERSION_MAX;
|
||||||
tls_clear_cipher ( tls, &tls->tx.cipherspec.active );
|
tls_clear_cipher ( tls, &tls->tx.cipherspec.active );
|
||||||
tls_clear_cipher ( tls, &tls->tx.cipherspec.pending );
|
tls_clear_cipher ( tls, &tls->tx.cipherspec.pending );
|
||||||
tls_clear_cipher ( tls, &tls->rx.cipherspec.active );
|
tls_clear_cipher ( tls, &tls->rx.cipherspec.active );
|
||||||
tls_clear_cipher ( tls, &tls->rx.cipherspec.pending );
|
tls_clear_cipher ( tls, &tls->rx.cipherspec.pending );
|
||||||
tls_clear_handshake ( tls );
|
tls_clear_handshake ( tls );
|
||||||
tls->client_random.gmt_unix_time = time ( NULL );
|
tls->client.random.gmt_unix_time = time ( NULL );
|
||||||
iob_populate ( &tls->rx.iobuf, &tls->rx.header, 0,
|
iob_populate ( &tls->rx.iobuf, &tls->rx.header, 0,
|
||||||
sizeof ( tls->rx.header ) );
|
sizeof ( tls->rx.header ) );
|
||||||
INIT_LIST_HEAD ( &tls->rx.data );
|
INIT_LIST_HEAD ( &tls->rx.data );
|
||||||
if ( ( rc = tls_generate_random ( tls, &tls->client_random.random,
|
if ( ( rc = tls_generate_random ( tls, &tls->client.random.random,
|
||||||
( sizeof ( tls->client_random.random ) ) ) ) != 0 ) {
|
( sizeof ( tls->client.random.random ) ) ) ) != 0 ) {
|
||||||
goto err_random;
|
goto err_random;
|
||||||
}
|
}
|
||||||
if ( ( rc = tls_session ( tls, name ) ) != 0 )
|
if ( ( rc = tls_session ( tls, name ) ) != 0 )
|
||||||
|
|
Loading…
Reference in New Issue