#define EINFO_EPERM_VERIFY \
__einfo_uniqify ( EINFO_EPERM, 0x02, \
"Handshake verification failed" )
-#define EPERM_CLIENT_CERT __einfo_error ( EINFO_EPERM_CLIENT_CERT )
-#define EINFO_EPERM_CLIENT_CERT \
- __einfo_uniqify ( EINFO_EPERM, 0x03, \
- "No suitable client certificate available" )
#define EPERM_RENEG_INSECURE __einfo_error ( EINFO_EPERM_RENEG_INSECURE )
#define EINFO_EPERM_RENEG_INSECURE \
__einfo_uniqify ( EINFO_EPERM, 0x04, \
x509_chain_put ( tls->client.chain );
tls->client.chain = NULL;
- /* Determine client certificate to be sent */
- cert = x509_find_key ( NULL, tls->client.key );
- if ( ! cert ) {
- DBGC ( tls, "TLS %p could not find certificate corresponding "
- "to private key\n", tls );
- rc = -EPERM_CLIENT_CERT;
- goto err_find;
- }
- x509_get ( cert );
- DBGC ( tls, "TLS %p selected client certificate %s\n",
- tls, x509_name ( cert ) );
-
/* Create client certificate chain */
tls->client.chain = x509_alloc_chain();
if ( ! tls->client.chain ) {
goto err_alloc;
}
- /* Append client certificate to chain */
- if ( ( rc = x509_append ( tls->client.chain, cert ) ) != 0 )
- goto err_append;
+ /* Determine client certificate to be sent, if any */
+ cert = x509_find_key ( NULL, tls->client.key );
+ if ( cert ) {
+
+ /* Get temporary reference to certificate */
+ x509_get ( cert );
+ DBGC ( tls, "TLS %p selected client certificate %s\n",
+ tls, x509_name ( cert ) );
+
+ /* Append client certificate to chain */
+ if ( ( rc = x509_append ( tls->client.chain, cert ) ) != 0 )
+ goto err_append;
+
+ /* Append any relevant issuer certificates */
+ if ( ( rc = x509_auto_append ( tls->client.chain,
+ &certstore ) ) != 0 )
+ goto err_auto_append;
+ } else {
- /* Append any relevant issuer certificates */
- if ( ( rc = x509_auto_append ( tls->client.chain, &certstore ) ) != 0 )
- goto err_auto_append;
+ /* Send an empty certificate chain */
+ DBGC ( tls, "TLS %p could not find certificate corresponding "
+ "to private key\n", tls );
+ }
- /* Drop local reference to client certificate */
+ /* Drop local reference (if any) to client certificate */
x509_put ( cert );
return 0;
err_auto_append:
err_append:
+ x509_put ( cert );
x509_chain_put ( tls->client.chain );
tls->client.chain = NULL;
err_alloc:
- x509_put ( cert );
- err_find:
return rc;
}
memcpy ( &tls->server.key, &cert->subject.public_key.raw,
sizeof ( tls->server.key ) );
- /* Schedule Client Key Exchange, Change Cipher, and Finished */
+ /* Schedule transmission of applicable handshake messages */
tls->tx.pending |= ( TLS_TX_CLIENT_KEY_EXCHANGE |
TLS_TX_CHANGE_CIPHER |
TLS_TX_FINISHED );
if ( tls->client.chain ) {
- tls->tx.pending |= ( TLS_TX_CERTIFICATE |
- TLS_TX_CERTIFICATE_VERIFY );
+ tls->tx.pending |= TLS_TX_CERTIFICATE;
+ if ( ! list_empty ( &tls->client.chain->links ) )
+ tls->tx.pending |= TLS_TX_CERTIFICATE_VERIFY;
}
tls_tx_resume ( tls );