mirror of
https://github.com/strophe/libstrophe.git
synced 2026-07-17 19:36:22 +00:00
Add support to retrieve the fingerprint of a public key from a cert.
Related-to: https://github.com/profanity-im/profanity/issues/2069 Signed-off-by: Steffen Jaeckel <s@jaeckel.eu>
This commit is contained in:
11
src/common.h
11
src/common.h
@@ -29,6 +29,17 @@
|
|||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
#include "snprintf.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 **/
|
/** handlers **/
|
||||||
#if (__STDC_VERSION__ >= 202000L)
|
#if (__STDC_VERSION__ >= 202000L)
|
||||||
typedef void *xmpp_void_handler;
|
typedef void *xmpp_void_handler;
|
||||||
|
|||||||
@@ -164,9 +164,13 @@ const char *xmpp_tlscert_get_description(xmpp_cert_element_t elmnt)
|
|||||||
"Expires On",
|
"Expires On",
|
||||||
"Public Key Algorithm",
|
"Public Key Algorithm",
|
||||||
"Certificate Signature Algorithm",
|
"Certificate Signature Algorithm",
|
||||||
"Fingerprint SHA-1",
|
"Certificate Fingerprint SHA-1",
|
||||||
"Fingerprint SHA-256",
|
"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)
|
if (elmnt < 0 || elmnt >= XMPP_CERT_ELEMENT_MAX)
|
||||||
return NULL;
|
return NULL;
|
||||||
return descriptions[elmnt];
|
return descriptions[elmnt];
|
||||||
|
|||||||
@@ -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);
|
gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_SHA256, smallbuf, &size);
|
||||||
hex_encode(buf, smallbuf, size);
|
hex_encode(buf, smallbuf, size);
|
||||||
tlscert->elements[XMPP_CERT_FINGERPRINT_SHA256] = strophe_strdup(ctx, buf);
|
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));
|
strophe_snprintf(buf, sizeof(buf), "%d", gnutls_x509_crt_get_version(cert));
|
||||||
tlscert->elements[XMPP_CERT_VERSION] = strophe_strdup(ctx, buf);
|
tlscert->elements[XMPP_CERT_VERSION] = strophe_strdup(ctx, buf);
|
||||||
|
|||||||
@@ -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 char buf[EVP_MAX_MD_SIZE];
|
||||||
unsigned int len;
|
unsigned int len;
|
||||||
|
int (*digest_fn)(const X509 *data, const EVP_MD *type, unsigned char *md,
|
||||||
|
unsigned int *len);
|
||||||
const EVP_MD *digest;
|
const EVP_MD *digest;
|
||||||
switch (el) {
|
switch (el) {
|
||||||
case XMPP_CERT_FINGERPRINT_SHA1:
|
case XMPP_CERT_FINGERPRINT_SHA1:
|
||||||
|
digest_fn = X509_digest;
|
||||||
digest = EVP_sha1();
|
digest = EVP_sha1();
|
||||||
break;
|
break;
|
||||||
case XMPP_CERT_FINGERPRINT_SHA256:
|
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();
|
digest = EVP_sha256();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return NULL;
|
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];
|
char fingerprint[4 * EVP_MAX_MD_SIZE];
|
||||||
hex_encode(fingerprint, buf, len);
|
hex_encode(fingerprint, buf, len);
|
||||||
return strophe_strdup(ctx, fingerprint);
|
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);
|
_get_fingerprint(ctx, cert, XMPP_CERT_FINGERPRINT_SHA1);
|
||||||
tlscert->elements[XMPP_CERT_FINGERPRINT_SHA256] =
|
tlscert->elements[XMPP_CERT_FINGERPRINT_SHA256] =
|
||||||
_get_fingerprint(ctx, cert, 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);
|
strophe_snprintf(buf, sizeof(buf), "%ld", X509_get_version(cert) + 1);
|
||||||
tlscert->elements[XMPP_CERT_VERSION] = strophe_strdup(ctx, buf);
|
tlscert->elements[XMPP_CERT_VERSION] = strophe_strdup(ctx, buf);
|
||||||
|
|||||||
23
strophe.h
23
strophe.h
@@ -251,17 +251,18 @@ typedef enum {
|
|||||||
* @ingroup TLS
|
* @ingroup TLS
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
XMPP_CERT_VERSION, /**< X.509 Version */
|
XMPP_CERT_VERSION, /**< X.509 Version */
|
||||||
XMPP_CERT_SERIALNUMBER, /**< SerialNumber */
|
XMPP_CERT_SERIALNUMBER, /**< SerialNumber */
|
||||||
XMPP_CERT_SUBJECT, /**< Subject */
|
XMPP_CERT_SUBJECT, /**< Subject */
|
||||||
XMPP_CERT_ISSUER, /**< Issuer */
|
XMPP_CERT_ISSUER, /**< Issuer */
|
||||||
XMPP_CERT_NOTBEFORE, /**< Issued on */
|
XMPP_CERT_NOTBEFORE, /**< Issued on */
|
||||||
XMPP_CERT_NOTAFTER, /**< Expires on */
|
XMPP_CERT_NOTAFTER, /**< Expires on */
|
||||||
XMPP_CERT_KEYALG, /**< Public Key Algorithm */
|
XMPP_CERT_KEYALG, /**< Public Key Algorithm */
|
||||||
XMPP_CERT_SIGALG, /**< Certificate Signature Algorithm */
|
XMPP_CERT_SIGALG, /**< Certificate Signature Algorithm */
|
||||||
XMPP_CERT_FINGERPRINT_SHA1, /**< Fingerprint SHA-1 */
|
XMPP_CERT_FINGERPRINT_SHA1, /**< Fingerprint SHA-1 */
|
||||||
XMPP_CERT_FINGERPRINT_SHA256, /**< Fingerprint SHA-256 */
|
XMPP_CERT_FINGERPRINT_SHA256, /**< Fingerprint SHA-256 */
|
||||||
XMPP_CERT_ELEMENT_MAX /**< Last element of the enum */
|
XMPP_CERT_PUBKEY_FINGERPRINT_SHA256, /**< SHA-256 fingerprint of pubkey */
|
||||||
|
XMPP_CERT_ELEMENT_MAX /**< Last element of the enum */
|
||||||
} xmpp_cert_element_t;
|
} xmpp_cert_element_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|||||||
Reference in New Issue
Block a user