Skip to content

Commit c7bf2a2

Browse files
committed
Add support to retrieve the fingerprint of a public key from a cert.
Related-to: profanity-im/profanity#2069 Signed-off-by: Steffen Jaeckel <[email protected]>
1 parent f8cda0f commit c7bf2a2

File tree

5 files changed

+46
-14
lines changed

5 files changed

+46
-14
lines changed

src/common.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,17 @@
2929
#include "parser.h"
3030
#include "snprintf.h"
3131

32+
/** Define your own `STROPHE_STATIC_ASSERT` if your compiler doesn't support one
33+
* of the below ones or define as noop if your compiler provides no replacement.
34+
*/
35+
#if !defined(STROPHE_STATIC_ASSERT)
36+
#if (__STDC_VERSION__ >= 202000L)
37+
#define STROPHE_STATIC_ASSERT(cond, msg) static_assert(cond, msg)
38+
#else
39+
#define STROPHE_STATIC_ASSERT(cond, msg) _Static_assert(cond, msg)
40+
#endif
41+
#endif
42+
3243
/** handlers **/
3344
#if (__STDC_VERSION__ >= 202000L)
3445
typedef void *xmpp_void_handler;

src/tls.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,9 +162,13 @@ const char *xmpp_tlscert_get_description(xmpp_cert_element_t elmnt)
162162
"Expires On",
163163
"Public Key Algorithm",
164164
"Certificate Signature Algorithm",
165-
"Fingerprint SHA-1",
166-
"Fingerprint SHA-256",
165+
"Certificate Fingerprint SHA-1",
166+
"Certificate Fingerprint SHA-256",
167+
"Public Key Fingerprint SHA-256",
167168
};
169+
STROPHE_STATIC_ASSERT(
170+
ARRAY_SIZE(descriptions) == XMPP_CERT_ELEMENT_MAX,
171+
"descriptions don't match the number of enum elements");
168172
if (elmnt < 0 || elmnt >= XMPP_CERT_ELEMENT_MAX)
169173
return NULL;
170174
return descriptions[elmnt];

src/tls_gnutls.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,12 @@ static xmpp_tlscert_t *_x509_to_tlscert(xmpp_ctx_t *ctx, gnutls_x509_crt_t cert)
334334
gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_SHA256, smallbuf, &size);
335335
hex_encode(buf, smallbuf, size);
336336
tlscert->elements[XMPP_CERT_FINGERPRINT_SHA256] = strophe_strdup(ctx, buf);
337+
size = sizeof(smallbuf);
338+
gnutls_x509_crt_get_key_id(cert, GNUTLS_KEYID_USE_SHA256, (void *)smallbuf,
339+
&size);
340+
hex_encode(buf, smallbuf, size);
341+
tlscert->elements[XMPP_CERT_PUBKEY_FINGERPRINT_SHA256] =
342+
strophe_strdup(ctx, buf);
337343

338344
strophe_snprintf(buf, sizeof(buf), "%d", gnutls_x509_crt_get_version(cert));
339345
tlscert->elements[XMPP_CERT_VERSION] = strophe_strdup(ctx, buf);

src/tls_openssl.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -376,18 +376,26 @@ _get_fingerprint(const xmpp_ctx_t *ctx, X509 *err_cert, xmpp_cert_element_t el)
376376
{
377377
unsigned char buf[EVP_MAX_MD_SIZE];
378378
unsigned int len;
379+
int (*digest_fn)(const X509 *data, const EVP_MD *type, unsigned char *md,
380+
unsigned int *len);
379381
const EVP_MD *digest;
380382
switch (el) {
381383
case XMPP_CERT_FINGERPRINT_SHA1:
384+
digest_fn = X509_digest;
382385
digest = EVP_sha1();
383386
break;
384387
case XMPP_CERT_FINGERPRINT_SHA256:
388+
digest_fn = X509_digest;
389+
digest = EVP_sha256();
390+
break;
391+
case XMPP_CERT_PUBKEY_FINGERPRINT_SHA256:
392+
digest_fn = X509_pubkey_digest;
385393
digest = EVP_sha256();
386394
break;
387395
default:
388396
return NULL;
389397
}
390-
if (X509_digest(err_cert, digest, buf, &len) != 0) {
398+
if (digest_fn(err_cert, digest, buf, &len) != 0) {
391399
char fingerprint[4 * EVP_MAX_MD_SIZE];
392400
hex_encode(fingerprint, buf, len);
393401
return strophe_strdup(ctx, fingerprint);
@@ -475,6 +483,8 @@ static xmpp_tlscert_t *_x509_to_tlscert(xmpp_ctx_t *ctx, X509 *cert)
475483
_get_fingerprint(ctx, cert, XMPP_CERT_FINGERPRINT_SHA1);
476484
tlscert->elements[XMPP_CERT_FINGERPRINT_SHA256] =
477485
_get_fingerprint(ctx, cert, XMPP_CERT_FINGERPRINT_SHA256);
486+
tlscert->elements[XMPP_CERT_PUBKEY_FINGERPRINT_SHA256] =
487+
_get_fingerprint(ctx, cert, XMPP_CERT_PUBKEY_FINGERPRINT_SHA256);
478488

479489
strophe_snprintf(buf, sizeof(buf), "%ld", X509_get_version(cert) + 1);
480490
tlscert->elements[XMPP_CERT_VERSION] = strophe_strdup(ctx, buf);

strophe.h

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -250,17 +250,18 @@ typedef enum {
250250
* @ingroup TLS
251251
*/
252252
typedef enum {
253-
XMPP_CERT_VERSION, /**< X.509 Version */
254-
XMPP_CERT_SERIALNUMBER, /**< SerialNumber */
255-
XMPP_CERT_SUBJECT, /**< Subject */
256-
XMPP_CERT_ISSUER, /**< Issuer */
257-
XMPP_CERT_NOTBEFORE, /**< Issued on */
258-
XMPP_CERT_NOTAFTER, /**< Expires on */
259-
XMPP_CERT_KEYALG, /**< Public Key Algorithm */
260-
XMPP_CERT_SIGALG, /**< Certificate Signature Algorithm */
261-
XMPP_CERT_FINGERPRINT_SHA1, /**< Fingerprint SHA-1 */
262-
XMPP_CERT_FINGERPRINT_SHA256, /**< Fingerprint SHA-256 */
263-
XMPP_CERT_ELEMENT_MAX /**< Last element of the enum */
253+
XMPP_CERT_VERSION, /**< X.509 Version */
254+
XMPP_CERT_SERIALNUMBER, /**< SerialNumber */
255+
XMPP_CERT_SUBJECT, /**< Subject */
256+
XMPP_CERT_ISSUER, /**< Issuer */
257+
XMPP_CERT_NOTBEFORE, /**< Issued on */
258+
XMPP_CERT_NOTAFTER, /**< Expires on */
259+
XMPP_CERT_KEYALG, /**< Public Key Algorithm */
260+
XMPP_CERT_SIGALG, /**< Certificate Signature Algorithm */
261+
XMPP_CERT_FINGERPRINT_SHA1, /**< Fingerprint SHA-1 */
262+
XMPP_CERT_FINGERPRINT_SHA256, /**< Fingerprint SHA-256 */
263+
XMPP_CERT_PUBKEY_FINGERPRINT_SHA256, /**< SHA-256 fingerprint of pubkey */
264+
XMPP_CERT_ELEMENT_MAX /**< Last element of the enum */
264265
} xmpp_cert_element_t;
265266

266267
typedef struct {

0 commit comments

Comments
 (0)