mirror of
https://github.com/ipxe/ipxe
synced 2026-10-07 15:05:42 +03:00
[tls] Use SHA-1 for TLS version 1.1 ECDSA signatures
We currently use the MD5+SHA1 algorithm for all signatures when using TLS version 1.1. This is incorrect for ECDSA (or for any non-RSA public-key algorithm): these should instead use SHA-1. Fix by using SHA-1 for any non-RSA public-key algorithm for TLS version 1.1. Provide a weak rsa_algorithm symbol to use in the comparison, to avoid unconditionally dragging in RSA support. Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
+36
-20
@@ -191,6 +191,9 @@ FILE_SECBOOT ( PERMITTED );
|
|||||||
__einfo_uniqify ( EINFO_EPROTO, 0x04, \
|
__einfo_uniqify ( EINFO_EPROTO, 0x04, \
|
||||||
"Certificate validation already in progress" )
|
"Certificate validation already in progress" )
|
||||||
|
|
||||||
|
/* Avoid dragging in RSA support unconditionally */
|
||||||
|
struct pubkey_algorithm rsa_algorithm __attribute__ (( weak ));
|
||||||
|
|
||||||
/** List of TLS session */
|
/** List of TLS session */
|
||||||
static LIST_HEAD ( tls_sessions );
|
static LIST_HEAD ( tls_sessions );
|
||||||
|
|
||||||
@@ -2197,14 +2200,12 @@ static int tls_send_client_key_exchange ( struct tls_connection *tls ) {
|
|||||||
* @ret rc Return status code
|
* @ret rc Return status code
|
||||||
*/
|
*/
|
||||||
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->key.digest;
|
|
||||||
struct asn1_cursor *key = privkey_cursor ( tls->client.key );
|
struct asn1_cursor *key = privkey_cursor ( tls->client.key );
|
||||||
struct tls_signature_hash_algorithm *sig_hash = NULL;
|
struct tls_signature_hash_algorithm *sig_hash = NULL;
|
||||||
struct asn1_builder builder = { NULL, 0 };
|
struct asn1_builder builder = { NULL, 0 };
|
||||||
struct x509_certificate *cert;
|
struct x509_certificate *cert;
|
||||||
struct pubkey_algorithm *pubkey;
|
struct pubkey_algorithm *pubkey;
|
||||||
size_t digestsize = digest->digestsize;
|
struct digest_algorithm *digest;
|
||||||
uint8_t tbshash[digestsize];
|
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
/* Sanity checks */
|
/* Sanity checks */
|
||||||
@@ -2221,8 +2222,11 @@ static int tls_send_certificate_verify ( struct tls_connection *tls ) {
|
|||||||
}
|
}
|
||||||
pubkey = cert->signature_algorithm->pubkey;
|
pubkey = cert->signature_algorithm->pubkey;
|
||||||
|
|
||||||
/* TLSv1.2 and later use explicit algorithm identifiers */
|
/* Identify signature and hash algorithm */
|
||||||
if ( tls_version ( tls, TLS_VERSION_TLS_1_2 ) ) {
|
if ( tls_version ( tls, TLS_VERSION_TLS_1_2 ) ) {
|
||||||
|
|
||||||
|
/* TLSv1.2 and above use explicit algorithm identifiers */
|
||||||
|
digest = tls->key.digest;
|
||||||
sig_hash = tls_signature_hash_algorithm ( pubkey, digest );
|
sig_hash = tls_signature_hash_algorithm ( pubkey, digest );
|
||||||
if ( ! sig_hash ) {
|
if ( ! sig_hash ) {
|
||||||
DBGC ( tls, "TLS %p could not identify (%s,%s) "
|
DBGC ( tls, "TLS %p could not identify (%s,%s) "
|
||||||
@@ -2231,27 +2235,18 @@ static int tls_send_certificate_verify ( struct tls_connection *tls ) {
|
|||||||
rc = -ENOTSUP_SIG_HASH;
|
rc = -ENOTSUP_SIG_HASH;
|
||||||
goto err_sig_hash;
|
goto err_sig_hash;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Generate digest */
|
} else {
|
||||||
if ( ( rc = tlskey_tbshash ( &tls->key, &tls_client, digest, NULL, 0,
|
|
||||||
tbshash ) ) != 0 ) {
|
|
||||||
DBGC ( tls, "TLS %p could not generate CertificateVerify "
|
|
||||||
"digest: %s\n", tls, strerror ( rc ) );
|
|
||||||
goto err_tbshash;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Sign digest */
|
/* TLSv1.1 and below use fixed algorithms */
|
||||||
if ( ( rc = pubkey_sign ( pubkey, key, digest, tbshash,
|
digest = ( ( pubkey == &rsa_algorithm ) ?
|
||||||
&builder ) ) != 0 ) {
|
&md5_sha1_algorithm : &sha1_algorithm );
|
||||||
DBGC ( tls, "TLS %p could not sign %s digest using %s client "
|
|
||||||
"private key: %s\n", tls, digest->name, pubkey->name,
|
|
||||||
strerror ( rc ) );
|
|
||||||
goto err_pubkey_sign;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Construct Certificate Verify record */
|
/* Construct Certificate Verify record */
|
||||||
{
|
{
|
||||||
|
size_t digestsize = digest->digestsize;
|
||||||
|
uint8_t tbshash[digestsize];
|
||||||
int use_sig_hash = ( ( sig_hash == NULL ) ? 0 : 1 );
|
int use_sig_hash = ( ( sig_hash == NULL ) ? 0 : 1 );
|
||||||
struct {
|
struct {
|
||||||
uint32_t type_length;
|
uint32_t type_length;
|
||||||
@@ -2259,6 +2254,25 @@ static int tls_send_certificate_verify ( struct tls_connection *tls ) {
|
|||||||
uint16_t signature_len;
|
uint16_t signature_len;
|
||||||
} __attribute__ (( packed )) header;
|
} __attribute__ (( packed )) header;
|
||||||
|
|
||||||
|
/* Generate digest */
|
||||||
|
if ( ( rc = tlskey_tbshash ( &tls->key, &tls_client, digest,
|
||||||
|
NULL, 0, tbshash ) ) != 0 ) {
|
||||||
|
DBGC ( tls, "TLS %p could not generate "
|
||||||
|
"CertificateVerify digest: %s\n",
|
||||||
|
tls, strerror ( rc ) );
|
||||||
|
goto err_tbshash;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sign digest */
|
||||||
|
if ( ( rc = pubkey_sign ( pubkey, key, digest, tbshash,
|
||||||
|
&builder ) ) != 0 ) {
|
||||||
|
DBGC ( tls, "TLS %p could not sign %s digest using "
|
||||||
|
"%s client private key: %s\n", tls,
|
||||||
|
digest->name, pubkey->name, strerror ( rc ) );
|
||||||
|
goto err_pubkey_sign;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Construct header */
|
||||||
header.type_length = ( cpu_to_le32 ( TLS_CERTIFICATE_VERIFY ) |
|
header.type_length = ( cpu_to_le32 ( TLS_CERTIFICATE_VERIFY ) |
|
||||||
htonl ( builder.len +
|
htonl ( builder.len +
|
||||||
sizeof ( header ) -
|
sizeof ( header ) -
|
||||||
@@ -2269,6 +2283,7 @@ static int tls_send_certificate_verify ( struct tls_connection *tls ) {
|
|||||||
}
|
}
|
||||||
header.signature_len = htons ( builder.len );
|
header.signature_len = htons ( builder.len );
|
||||||
|
|
||||||
|
/* Prepend header */
|
||||||
if ( ( rc = asn1_prepend_raw ( &builder, &header,
|
if ( ( rc = asn1_prepend_raw ( &builder, &header,
|
||||||
sizeof ( header ) ) ) != 0 ) {
|
sizeof ( header ) ) ) != 0 ) {
|
||||||
DBGC ( tls, "TLS %p could not construct Certificate "
|
DBGC ( tls, "TLS %p could not construct Certificate "
|
||||||
@@ -2870,7 +2885,8 @@ static int tls_verify_signature ( struct tls_connection *tls,
|
|||||||
sig_hash = &tmp;
|
sig_hash = &tmp;
|
||||||
memset ( sig_hash, 0, sizeof ( *sig_hash ) );
|
memset ( sig_hash, 0, sizeof ( *sig_hash ) );
|
||||||
sig_hash->pubkey = suite->pubkey;
|
sig_hash->pubkey = suite->pubkey;
|
||||||
sig_hash->digest = &md5_sha1_algorithm;
|
sig_hash->digest = ( ( suite->pubkey == &rsa_algorithm ) ?
|
||||||
|
&md5_sha1_algorithm : &sha1_algorithm );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Verify signature */
|
/* Verify signature */
|
||||||
|
|||||||
Reference in New Issue
Block a user