summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortb <>2024-10-17 06:19:06 +0000
committertb <>2024-10-17 06:19:06 +0000
commit46b9e823a03f4d0f680a05c9f7d55e5277120920 (patch)
tree33f137101108b97e017678abe4dd14ea060c62f8
parentd11f92ed77a84750d747201a5ebdf6e31f5d11e7 (diff)
downloadopenbsd-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.c52
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
333static int 333static int
334ssl_cert_signature_md_nid(X509 *x509) 334ssl_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,
347static int 347 &flags))
348ssl_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
362static int 363static int
363ssl_security_cert_sig(const SSL_CTX *ctx, const SSL *ssl, X509 *x509, int secop) 364ssl_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);