const void *data, size_t len );
static void tls_clear_cipher ( struct tls_connection *tls,
struct tls_cipherspec *cipherspec );
+static void tls_verify_handshake ( struct tls_connection *tls, void *out );
/******************************************************************************
*
static void tls_generate_master_secret ( struct tls_connection *tls,
const void *pre_master_secret,
size_t pre_master_secret_len ) {
+ struct digest_algorithm *digest = tls->handshake_digest;
+ uint8_t digest_out[ digest->digestsize ];
+
+ /* Generate handshake digest */
+ tls_verify_handshake ( tls, digest_out );
- DBGC ( tls, "TLS %p pre-master-secret:\n", tls );
+ /* Show inputs */
+ DBGC ( tls, "TLS %p pre-master secret:\n", tls );
DBGC_HD ( tls, pre_master_secret, pre_master_secret_len );
DBGC ( tls, "TLS %p client random bytes:\n", tls );
DBGC_HD ( tls, &tls->client.random, sizeof ( tls->client.random ) );
DBGC ( tls, "TLS %p server random bytes:\n", tls );
DBGC_HD ( tls, &tls->server.random, sizeof ( tls->server.random ) );
+ DBGC ( tls, "TLS %p session hash:\n", tls );
+ DBGC_HD ( tls, digest_out, sizeof ( digest_out ) );
- tls_prf_label ( tls, pre_master_secret, pre_master_secret_len,
- &tls->master_secret, sizeof ( tls->master_secret ),
- "master secret",
- &tls->client.random, sizeof ( tls->client.random ),
- &tls->server.random, sizeof ( tls->server.random ) );
+ /* Generate master secret */
+ if ( tls->extended_master_secret ) {
+ tls_prf_label ( tls, pre_master_secret, pre_master_secret_len,
+ &tls->master_secret,
+ sizeof ( tls->master_secret ),
+ "extended master secret",
+ digest_out, sizeof ( digest_out ) );
+ } else {
+ tls_prf_label ( tls, pre_master_secret, pre_master_secret_len,
+ &tls->master_secret,
+ sizeof ( tls->master_secret ),
+ "master secret",
+ &tls->client.random,
+ sizeof ( tls->client.random ),
+ &tls->server.random,
+ sizeof ( tls->server.random ) );
+ }
- DBGC ( tls, "TLS %p generated master secret:\n", tls );
+ /* Show output */
+ DBGC ( tls, "TLS %p generated %smaster secret:\n", tls,
+ ( tls->extended_master_secret ? "extended ": "" ) );
DBGC_HD ( tls, &tls->master_secret, sizeof ( tls->master_secret ) );
}
uint16_t code[TLS_NUM_NAMED_CURVES];
} __attribute__ (( packed )) data;
} __attribute__ (( packed )) *named_curve_ext;
+ struct {
+ uint16_t type;
+ uint16_t len;
+ } __attribute__ (( packed )) *extended_master_secret_ext;
struct {
typeof ( *server_name_ext ) server_name;
typeof ( *max_fragment_length_ext ) max_fragment_length;
typeof ( *signature_algorithms_ext ) signature_algorithms;
typeof ( *renegotiation_info_ext ) renegotiation_info;
typeof ( *session_ticket_ext ) session_ticket;
+ typeof ( *extended_master_secret_ext ) extended_master_secret;
typeof ( *named_curve_ext )
named_curve[TLS_NUM_NAMED_CURVES ? 1 : 0];
} __attribute__ (( packed )) *extensions;
memcpy ( session_ticket_ext->data.data, session->ticket,
sizeof ( session_ticket_ext->data.data ) );
+ /* Construct extended master secret extension */
+ extended_master_secret_ext = &extensions->extended_master_secret;
+ extended_master_secret_ext->type
+ = htons ( TLS_EXTENDED_MASTER_SECRET );
+ extended_master_secret_ext->len = 0;
+
/* Construct named curves extension, if applicable */
if ( sizeof ( extensions->named_curve ) ) {
named_curve_ext = &extensions->named_curve[0];
uint8_t len;
uint8_t data[0];
} __attribute__ (( packed )) *reneg = NULL;
+ const struct {
+ uint8_t data[0];
+ } __attribute__ (( packed )) *ems = NULL;
uint16_t version;
size_t exts_len;
size_t ext_len;
return -EINVAL_HELLO;
}
break;
+ case htons ( TLS_EXTENDED_MASTER_SECRET ) :
+ ems = ( ( void * ) ext->data );
+ break;
}
}
}
memcpy ( &tls->server.random, &hello_a->random,
sizeof ( tls->server.random ) );
+ /* Handle extended master secret */
+ tls->extended_master_secret = ( !! ems );
+
/* Check session ID */
if ( hello_a->session_id_len &&
( hello_a->session_id_len == tls->session_id_len ) &&