diff options
| author | Bob Beck <[email protected]> | 2026-09-04 01:51:43 +0200 |
|---|---|---|
| committer | Tomas Mraz <[email protected]> | 2026-09-17 18:44:11 +0200 |
| commit | 90c3f5110fc66dce374512738f2667c29eca2c5e (patch) | |
| tree | 212630b4fdbb726977f85b9be75f3bebd38cfaa1 /include | |
| parent | Compute X509_get_signature_info() on demand, not in the cache (diff) | |
| download | openssl-90c3f5110fc66dce374512738f2667c29eca2c5e.tar.gz openssl-90c3f5110fc66dce374512738f2667c29eca2c5e.zip | |
Use SipHash for the internal fingerprint
Replace SHA-1 with SipHash-2-4 (fixed key, 64-bit output) for the
internal X509 and X509_CRL fingerprint.
Always build crypto/siphash; no-siphash now only removes the provider
MAC.
Reviewed-by: Mounir Idrassi <[email protected]>
Reviewed-by: Nikola Pajkovsky <[email protected]>
Merge-date: Thu Sep 17 16:44:35 2026
Merged-from: https://github.com/openssl/openssl/pull/32686
Diffstat (limited to 'include')
| -rw-r--r-- | include/crypto/x509.h | 46 |
1 files changed, 34 insertions, 12 deletions
diff --git a/include/crypto/x509.h b/include/crypto/x509.h index 515ea155309..e89f2fed508 100644 --- a/include/crypto/x509.h +++ b/include/crypto/x509.h @@ -19,6 +19,19 @@ #include "crypto/types.h" #include <crypto/asn1.h> +#include <crypto/siphash.h> + +/* + * Size in bytes of the internal X509 / X509_CRL fingerprint, see + * ossl_x509_internal_fingerprint(). The fingerprint only short-circuits + * X509_cmp() and X509_CRL_match(), which compare the encodings on a match, + * so a collision costs one extra memcmp. With 64 bits a collision among + * n objects has probability about n^2 / 2^65: one in 10^12 for 10,000 + * certificates, and even odds only at around 2^32 of them. The SipHash key + * is fixed, so an attacker can craft certificates that collide, but gains + * only that memcmp per colliding pair on certificates they had to supply. + */ +#define OSSL_X509_FINGERPRINT_SIZE SIPHASH_MIN_DIGEST_SIZE /* Internal X509 structures and functions: not for application use */ @@ -119,8 +132,12 @@ struct X509_crl_st { ASN1_INTEGER *crl_number; ASN1_INTEGER *base_crl_number; STACK_OF(GENERAL_NAMES) *issuers; - /* internal-use fingerprint for X509_CRL_match(), see ossl_x509_internal_fingerprint() */ - unsigned char fingerprint[SHA_DIGEST_LENGTH]; + /* + * Internal-use fingerprint for X509_CRL_match(), see + * ossl_x509_internal_fingerprint(). Not cryptographically secure and + * not collision free: a match is confirmed by comparing the CRLs. + */ + unsigned char fingerprint[OSSL_X509_FINGERPRINT_SIZE]; /* alternative method to handle this CRL */ const X509_CRL_METHOD *meth; void *meth_data; @@ -197,8 +214,12 @@ struct x509_st { STACK_OF(IPAddressFamily) *rfc3779_addr; struct ASIdentifiers_st *rfc3779_asid; #endif - /* internal-use fingerprint for X509_cmp(), see ossl_x509_internal_fingerprint() */ - unsigned char fingerprint[SHA_DIGEST_LENGTH]; + /* + * Internal-use fingerprint for X509_cmp(), see + * ossl_x509_internal_fingerprint(). Not cryptographically secure and + * not collision free: a match is confirmed by comparing the certificates. + */ + unsigned char fingerprint[OSSL_X509_FINGERPRINT_SIZE]; X509_CERT_AUX *aux; CRYPTO_RWLOCK *lock; volatile int ex_cached; @@ -324,22 +345,23 @@ int ossl_x509v3_cache_extensions(const X509 *x); * The fingerprint is cached in X509 / X509_CRL fingerprint and used only for * internal identity comparison (X509_cmp(), X509_CRL_match()); it is never * returned to callers, so the algorithm is an implementation detail - * (currently SHA-1). It uses the built-in implementation directly rather - * than fetching one, so the result depends on neither the library context - * nor the property query string of the object and stays valid if the object - * is moved to another library context. It fails only if the object cannot be + * (currently SipHash-2-4 with a fixed key and 64-bit output; a collision + * only costs the callers a fall through to their encoding comparison). + * Callers hash the whole signed object (X509, X509_CRL). No algorithm + * is fetched, so the result depends on neither the library context nor the + * property query string of the object and stays valid if the object is + * moved to another library context. It fails only if the object cannot be * DER encoded, for instance a certificate still under construction, or on * an allocation failure in the encoder. * * @param it the ASN1_ITEM describing @p val * @param val the object to encode and hash - * @param hash output buffer for the fingerprint - * @param hash_size size in bytes of @p hash, must be at least - * SHA_DIGEST_LENGTH + * @param hash output buffer for the fingerprint, OSSL_X509_FINGERPRINT_SIZE + * bytes * @returns 1 on success, 0 on failure */ int ossl_x509_internal_fingerprint(const ASN1_ITEM *it, const void *val, - unsigned char *hash, size_t hash_size); + unsigned char *hash); int ossl_x509_set0_libctx(X509 *x, OSSL_LIB_CTX *libctx, const char *propq); int ossl_x509_crl_set0_libctx(X509_CRL *x, OSSL_LIB_CTX *libctx, |
