diff options
author | tb <> | 2024-10-17 06:19:06 +0000 |
---|---|---|
committer | tb <> | 2024-10-17 06:19:06 +0000 |
commit | 46b9e823a03f4d0f680a05c9f7d55e5277120920 (patch) | |
tree | 33f137101108b97e017678abe4dd14ea060c62f8 | |
parent | d11f92ed77a84750d747201a5ebdf6e31f5d11e7 (diff) | |
download | openbsd-46b9e823a03f4d0f680a05c9f7d55e5277120920.tar.gz openbsd-46b9e823a03f4d0f680a05c9f7d55e5277120920.tar.bz2 openbsd-46b9e823a03f4d0f680a05c9f7d55e5277120920.zip |
libssl: rework cert signature security level
This switches to using the X509_get_signature_info() API instead of hand
rolling a part of it. This is slightly tangly since the security level API
is strange. In particular, some failures are passed to the security level
callback so that applications can override them.
This makes the security level API handle RSA-PSS and EdDSA certificates
correctly and the handshake with such can progress a bit further. Of note,
we check that the certs are actually suitable for use in TLS per RFC 8446
contrary to what OpenSSL does.
ok beck jsing
-rw-r--r-- | src/lib/libssl/ssl_seclevel.c | 52 |
1 files changed, 28 insertions, 24 deletions
diff --git a/src/lib/libssl/ssl_seclevel.c b/src/lib/libssl/ssl_seclevel.c index 6a5d16bfaa..1448368e71 100644 --- a/src/lib/libssl/ssl_seclevel.c +++ b/src/lib/libssl/ssl_seclevel.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssl_seclevel.c,v 1.28 2024/05/09 07:12:03 tb Exp $ */ | 1 | /* $OpenBSD: ssl_seclevel.c,v 1.29 2024/10/17 06:19:06 tb Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2020-2022 Theo Buehler <tb@openbsd.org> | 3 | * Copyright (c) 2020-2022 Theo Buehler <tb@openbsd.org> |
4 | * | 4 | * |
@@ -331,45 +331,49 @@ ssl_security_cert_key(const SSL_CTX *ctx, const SSL *ssl, X509 *x509, int secop) | |||
331 | } | 331 | } |
332 | 332 | ||
333 | static int | 333 | static int |
334 | ssl_cert_signature_md_nid(X509 *x509) | 334 | ssl_security_cert_sig_security_bits(X509 *x509, int *out_md_nid) |
335 | { | 335 | { |
336 | int md_nid, signature_nid; | 336 | int pkey_nid, security_bits; |
337 | uint32_t flags; | ||
337 | 338 | ||
338 | if ((signature_nid = X509_get_signature_nid(x509)) == NID_undef) | 339 | *out_md_nid = NID_undef; |
339 | return NID_undef; | ||
340 | 340 | ||
341 | if (!OBJ_find_sigid_algs(signature_nid, &md_nid, NULL)) | 341 | /* |
342 | return NID_undef; | 342 | * Returning -1 security bits makes the default security callback fail |
343 | 343 | * to match bonkers behavior in OpenSSL. This in turn lets a security | |
344 | return md_nid; | 344 | * callback override such failures. |
345 | } | 345 | */ |
346 | 346 | if (!X509_get_signature_info(x509, out_md_nid, &pkey_nid, &security_bits, | |
347 | static int | 347 | &flags)) |
348 | ssl_cert_md_nid_security_bits(int md_nid) | ||
349 | { | ||
350 | const EVP_MD *md; | ||
351 | |||
352 | if (md_nid == NID_undef) | ||
353 | return -1; | 348 | return -1; |
354 | 349 | /* | |
355 | if ((md = EVP_get_digestbynid(md_nid)) == NULL) | 350 | * OpenSSL doesn't check flags. Test RSA-PSS certs we were provided have |
351 | * a salt length distinct from hash length and thus fail this check. | ||
352 | */ | ||
353 | if ((flags & X509_SIG_INFO_TLS) == 0) | ||
356 | return -1; | 354 | return -1; |
357 | 355 | ||
358 | /* Assume 4 bits of collision resistance for each hash octet. */ | 356 | /* Weird OpenSSL behavior only relevant for EdDSA certs in LibreSSL. */ |
359 | return EVP_MD_size(md) * 4; | 357 | if (*out_md_nid == NID_undef) |
358 | *out_md_nid = pkey_nid; | ||
359 | |||
360 | return security_bits; | ||
360 | } | 361 | } |
361 | 362 | ||
362 | static int | 363 | static int |
363 | ssl_security_cert_sig(const SSL_CTX *ctx, const SSL *ssl, X509 *x509, int secop) | 364 | ssl_security_cert_sig(const SSL_CTX *ctx, const SSL *ssl, X509 *x509, int secop) |
364 | { | 365 | { |
365 | int md_nid, security_bits; | 366 | int md_nid = NID_undef, security_bits = -1; |
366 | 367 | ||
367 | /* Don't check signature if self signed. */ | 368 | /* Don't check signature if self signed. */ |
368 | if ((X509_get_extension_flags(x509) & EXFLAG_SS) != 0) | 369 | if ((X509_get_extension_flags(x509) & EXFLAG_SS) != 0) |
369 | return 1; | 370 | return 1; |
370 | 371 | ||
371 | md_nid = ssl_cert_signature_md_nid(x509); | 372 | /* |
372 | security_bits = ssl_cert_md_nid_security_bits(md_nid); | 373 | * The default security callback fails on -1 security bits. It ignores |
374 | * the md_nid (aka version) argument we pass from here. | ||
375 | */ | ||
376 | security_bits = ssl_security_cert_sig_security_bits(x509, &md_nid); | ||
373 | 377 | ||
374 | if (ssl != NULL) | 378 | if (ssl != NULL) |
375 | return ssl_security(ssl, secop, security_bits, md_nid, x509); | 379 | return ssl_security(ssl, secop, security_bits, md_nid, x509); |