-/* $OpenBSD: cert.c,v 1.141 2024/06/07 08:36:54 tb Exp $ */
+/* $OpenBSD: cert.c,v 1.142 2024/06/08 13:28:35 tb Exp $ */
/*
* Copyright (c) 2022 Theo Buehler <tb@openbsd.org>
* Copyright (c) 2021 Job Snijders <job@openbsd.org>
if (!cert_check_subject_and_issuer(fn, x))
goto out;
+ if (!x509_cache_extensions(x, fn))
+ goto out;
+
if (X509_get_key_usage(x) != KU_DIGITAL_SIGNATURE) {
warnx("%s: RFC 6487 section 4.8.4: KU must be digitalSignature",
fn);
goto out;
}
- /* Cache X509v3 extensions, see X509_check_ca(3). */
- if (X509_check_purpose(x, -1, -1) <= 0) {
- warnx("%s: could not cache X509v3 extensions", fn);
+ if (!x509_cache_extensions(x, fn))
goto out;
- }
if (X509_get_version(x) != 2) {
warnx("%s: RFC 6487 4.1: X.509 version must be v3", fn);
-/* $OpenBSD: cms.c,v 1.45 2024/05/24 12:57:20 tb Exp $ */
+/* $OpenBSD: cms.c,v 1.46 2024/06/08 13:28:35 tb Exp $ */
/*
* Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
*
goto out;
}
- /* Cache X509v3 extensions, see X509_check_ca(3). */
- if (X509_check_purpose(*xp, -1, -1) <= 0) {
- warnx("%s: could not cache X509v3 extensions", fn);
+ if (!x509_cache_extensions(*xp, fn))
goto out;
- }
if (!x509_get_notafter(*xp, fn, ¬after))
goto out;
-/* $OpenBSD: extern.h,v 1.221 2024/06/04 04:17:18 tb Exp $ */
+/* $OpenBSD: extern.h,v 1.222 2024/06/08 13:28:35 tb Exp $ */
/*
* Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
*
/* X509 helpers. */
void x509_init_oid(void);
+int x509_cache_extensions(X509 *, const char *);
int x509_get_aia(X509 *, const char *, char **);
int x509_get_aki(X509 *, const char *, char **);
int x509_get_sia(X509 *, const char *, char **);
-/* $OpenBSD: x509.c,v 1.94 2024/06/07 08:36:54 tb Exp $ */
+/* $OpenBSD: x509.c,v 1.95 2024/06/08 13:28:35 tb Exp $ */
/*
* Copyright (c) 2022 Theo Buehler <tb@openbsd.org>
* Copyright (c) 2021 Claudio Jeker <claudio@openbsd.org>
}
}
+/*
+ * A number of critical OpenSSL API functions can't properly indicate failure
+ * and are unreliable if the extensions aren't already cached. An old trick is
+ * to cache the extensions using an error-checked call to X509_check_purpose()
+ * with a purpose of -1. This way functions such as X509_check_ca(), X509_cmp(),
+ * X509_get_key_usage(), X509_get_extended_key_usage() won't lie.
+ *
+ * Should be called right after deserialization and is essentially free to call
+ * multiple times.
+ */
+int
+x509_cache_extensions(X509 *x509, const char *fn)
+{
+ if (X509_check_purpose(x509, -1, 0) <= 0) {
+ warnx("%s: could not cache X509v3 extensions", fn);
+ return 0;
+ }
+ return 1;
+}
+
/*
* Parse X509v3 authority key identifier (AKI), RFC 6487 sec. 4.8.3.
* Returns the AKI or NULL if it could not be parsed.