diff --git a/src/common.h b/src/common.h index a367367a..81765a44 100644 --- a/src/common.h +++ b/src/common.h @@ -29,6 +29,17 @@ #include "parser.h" #include "snprintf.h" +/** Define your own `STROPHE_STATIC_ASSERT` if your compiler doesn't support one + * of the below ones or define as noop if your compiler provides no replacement. + */ +#if !defined(STROPHE_STATIC_ASSERT) +#if (__STDC_VERSION__ >= 202000L) +#define STROPHE_STATIC_ASSERT(cond, msg) static_assert(cond, msg) +#else +#define STROPHE_STATIC_ASSERT(cond, msg) _Static_assert(cond, msg) +#endif +#endif + /** handlers **/ #if (__STDC_VERSION__ >= 202000L) typedef void *xmpp_void_handler; diff --git a/src/tls.c b/src/tls.c index 5d084711..bb138990 100644 --- a/src/tls.c +++ b/src/tls.c @@ -166,9 +166,13 @@ const char *xmpp_tlscert_get_description(xmpp_cert_element_t elmnt) "Expires On", "Public Key Algorithm", "Certificate Signature Algorithm", - "Fingerprint SHA-1", - "Fingerprint SHA-256", + "Certificate Fingerprint SHA-1", + "Certificate Fingerprint SHA-256", + "Public Key Fingerprint SHA-256", }; + STROPHE_STATIC_ASSERT( + ARRAY_SIZE(descriptions) == XMPP_CERT_ELEMENT_MAX, + "descriptions don't match the number of enum elements"); if (elmnt < 0 || elmnt >= XMPP_CERT_ELEMENT_MAX) return NULL; return descriptions[elmnt]; diff --git a/src/tls_gnutls.c b/src/tls_gnutls.c index ecd85bc9..0aa7c284 100644 --- a/src/tls_gnutls.c +++ b/src/tls_gnutls.c @@ -334,6 +334,12 @@ static xmpp_tlscert_t *_x509_to_tlscert(xmpp_ctx_t *ctx, gnutls_x509_crt_t cert) gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_SHA256, smallbuf, &size); hex_encode(buf, smallbuf, size); tlscert->elements[XMPP_CERT_FINGERPRINT_SHA256] = strophe_strdup(ctx, buf); + size = sizeof(smallbuf); + gnutls_x509_crt_get_key_id(cert, GNUTLS_KEYID_USE_SHA256, (void *)smallbuf, + &size); + hex_encode(buf, smallbuf, size); + tlscert->elements[XMPP_CERT_PUBKEY_FINGERPRINT_SHA256] = + strophe_strdup(ctx, buf); strophe_snprintf(buf, sizeof(buf), "%d", gnutls_x509_crt_get_version(cert)); tlscert->elements[XMPP_CERT_VERSION] = strophe_strdup(ctx, buf); diff --git a/src/tls_openssl.c b/src/tls_openssl.c index df141cac..67d2c8a8 100644 --- a/src/tls_openssl.c +++ b/src/tls_openssl.c @@ -376,18 +376,26 @@ _get_fingerprint(const xmpp_ctx_t *ctx, X509 *err_cert, xmpp_cert_element_t el) { unsigned char buf[EVP_MAX_MD_SIZE]; unsigned int len; + int (*digest_fn)(const X509 *data, const EVP_MD *type, unsigned char *md, + unsigned int *len); const EVP_MD *digest; switch (el) { case XMPP_CERT_FINGERPRINT_SHA1: + digest_fn = X509_digest; digest = EVP_sha1(); break; case XMPP_CERT_FINGERPRINT_SHA256: + digest_fn = X509_digest; + digest = EVP_sha256(); + break; + case XMPP_CERT_PUBKEY_FINGERPRINT_SHA256: + digest_fn = X509_pubkey_digest; digest = EVP_sha256(); break; default: return NULL; } - if (X509_digest(err_cert, digest, buf, &len) != 0) { + if (digest_fn(err_cert, digest, buf, &len) != 0) { char fingerprint[4 * EVP_MAX_MD_SIZE]; hex_encode(fingerprint, buf, len); return strophe_strdup(ctx, fingerprint); @@ -475,6 +483,8 @@ static xmpp_tlscert_t *_x509_to_tlscert(xmpp_ctx_t *ctx, X509 *cert) _get_fingerprint(ctx, cert, XMPP_CERT_FINGERPRINT_SHA1); tlscert->elements[XMPP_CERT_FINGERPRINT_SHA256] = _get_fingerprint(ctx, cert, XMPP_CERT_FINGERPRINT_SHA256); + tlscert->elements[XMPP_CERT_PUBKEY_FINGERPRINT_SHA256] = + _get_fingerprint(ctx, cert, XMPP_CERT_PUBKEY_FINGERPRINT_SHA256); strophe_snprintf(buf, sizeof(buf), "%ld", X509_get_version(cert) + 1); tlscert->elements[XMPP_CERT_VERSION] = strophe_strdup(ctx, buf); diff --git a/strophe.h b/strophe.h index 18ca3e19..dec85932 100644 --- a/strophe.h +++ b/strophe.h @@ -250,17 +250,18 @@ typedef enum { * @ingroup TLS */ typedef enum { - XMPP_CERT_VERSION, /**< X.509 Version */ - XMPP_CERT_SERIALNUMBER, /**< SerialNumber */ - XMPP_CERT_SUBJECT, /**< Subject */ - XMPP_CERT_ISSUER, /**< Issuer */ - XMPP_CERT_NOTBEFORE, /**< Issued on */ - XMPP_CERT_NOTAFTER, /**< Expires on */ - XMPP_CERT_KEYALG, /**< Public Key Algorithm */ - XMPP_CERT_SIGALG, /**< Certificate Signature Algorithm */ - XMPP_CERT_FINGERPRINT_SHA1, /**< Fingerprint SHA-1 */ - XMPP_CERT_FINGERPRINT_SHA256, /**< Fingerprint SHA-256 */ - XMPP_CERT_ELEMENT_MAX /**< Last element of the enum */ + XMPP_CERT_VERSION, /**< X.509 Version */ + XMPP_CERT_SERIALNUMBER, /**< SerialNumber */ + XMPP_CERT_SUBJECT, /**< Subject */ + XMPP_CERT_ISSUER, /**< Issuer */ + XMPP_CERT_NOTBEFORE, /**< Issued on */ + XMPP_CERT_NOTAFTER, /**< Expires on */ + XMPP_CERT_KEYALG, /**< Public Key Algorithm */ + XMPP_CERT_SIGALG, /**< Certificate Signature Algorithm */ + XMPP_CERT_FINGERPRINT_SHA1, /**< Fingerprint SHA-1 */ + XMPP_CERT_FINGERPRINT_SHA256, /**< Fingerprint SHA-256 */ + XMPP_CERT_PUBKEY_FINGERPRINT_SHA256, /**< SHA-256 fingerprint of pubkey */ + XMPP_CERT_ELEMENT_MAX /**< Last element of the enum */ } xmpp_cert_element_t; typedef struct {