aboutsummaryrefslogtreecommitdiffstats
path: root/src/include/ipxe/x509.h
diff options
context:
space:
mode:
authorMichael Brown <mcb30@ipxe.org>2024-02-14 16:02:43 +0000
committerMichael Brown <mcb30@ipxe.org>2024-02-15 13:13:08 +0000
commit929f06a76de37612015882af592997a7da15a82d (patch)
tree0c3a91b4129c9754757a6431a623eb75518a9bee /src/include/ipxe/x509.h
parent943d75b557a8bf857d651e8116a7368b9d284e41 (diff)
downloadipxe-929f06a76de37612015882af592997a7da15a82d.tar.gz
[crypto] Allow for multiple cross-signed certificate download attempts
Certificates issued by Let's Encrypt have two options for their chain of trust: the chain can either terminate in the self-signed ISRG Root X1 root certificate, or in an intermediate ISRG Root X1 certificate that is signed in turn by the self-signed DST Root CA X3 root certificate. This is a historical artifact: when Let's Encrypt first launched as a project, the chain ending in DST Root CA X3 was used since existing clients would not have recognised the ISRG Root X1 certificate as a trusted root certificate. The DST Root CA X3 certificate expired in September 2021, and so is no longer trusted by clients (such as iPXE) that validate the expiry times of all certificates in the certificate chain. In order to maintain usability of certificates on older Android devices, the default certificate chain provided by Let's Encrypt still terminates in DST Root CA X3, even though that certificate has now expired. On newer devices which include ISRG Root X1 as a trusted root certificate, the intermediate version of ISRG Root X1 in the certificate chain is ignored and validation is performed as though the chain had terminated in the self-signed ISRG Root X1 root certificate. On older Android devices which do not include ISRG Root X1 as a trusted root certificate, the validation succeeds since Android chooses to ignore expiry times for root certificates and so continues to trust the DST Root CA X3 root certificate. This backwards compatibility hack unfortunately breaks the cross- signing mechanism used by iPXE, which assumes that the certificate chain will always terminate in a non-expired root certificate. Generalise the validator's cross-signed certificate download mechanism to walk up the certificate chain in the event of a failure, attempting to find a replacement cross-signed certificate chain starting from the next level up. This allows the validator to step over the expired (and hence invalidatable) DST Root CA X3 certificate, and instead download the cross-signed version of the ISRG Root X1 certificate. This generalisation also gives us the ability to handle servers that provide a full certificate chain including their root certificate: iPXE will step over the untrusted public root certificate and attempt to find a cross-signed version of it instead. Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/include/ipxe/x509.h')
-rw-r--r--src/include/ipxe/x509.h22
1 files changed, 22 insertions, 0 deletions
diff --git a/src/include/ipxe/x509.h b/src/include/ipxe/x509.h
index d2ba49fbb..87323cec0 100644
--- a/src/include/ipxe/x509.h
+++ b/src/include/ipxe/x509.h
@@ -171,6 +171,28 @@ struct x509_link {
struct list_head list;
/** Certificate */
struct x509_certificate *cert;
+ /** Flags */
+ unsigned int flags;
+};
+
+/** X.509 certficate chain link flags */
+enum x509_link_flags {
+ /** Cross-signed certificate download has been attempted
+ *
+ * This indicates that a cross-signature download attempt has
+ * been made to find a cross-signed issuer for this link's
+ * certificate.
+ */
+ X509_LINK_FL_CROSSED = 0x0001,
+ /** OCSP has been attempted
+ *
+ * This indicates that an OCSP attempt has been made using
+ * this link's certificate as an issuer. (We record the flag
+ * on the issuer rather than on the issued certificate, since
+ * we want to retry OCSP if an issuer is replaced with a
+ * downloaded cross-signed certificate.)
+ */
+ X509_LINK_FL_OCSPED = 0x0002,
};
/** An X.509 certificate chain */