+static int
+ConnSSL_InitCertFp( CONNECTION *c )
+{
+ const char hex[] = "0123456789abcdef";
+ int i;
+
+#ifdef HAVE_LIBSSL
+ unsigned char digest[EVP_MAX_MD_SIZE];
+ unsigned int digest_size;
+ X509 *cert;
+
+ cert = SSL_get_peer_certificate(c->ssl_state.ssl);
+ if (!cert)
+ return 0;
+
+ if (!X509_digest(cert, EVP_sha256(), digest, &digest_size)) {
+ X509_free(cert);
+ return 0;
+ }
+
+ X509_free(cert);
+#endif /* HAVE_LIBSSL */
+#ifdef HAVE_LIBGNUTLS
+ gnutls_x509_crt_t cert;
+ unsigned int cert_list_size;
+ const gnutls_datum_t *cert_list;
+ unsigned char digest[MAX_HASH_SIZE];
+ size_t digest_size;
+
+ if (gnutls_certificate_type_get(c->ssl_state.gnutls_session) !=
+ GNUTLS_CRT_X509)
+ return 0;
+
+ if (gnutls_x509_crt_init(&cert) != GNUTLS_E_SUCCESS)
+ return 0;
+
+ cert_list_size = 0;
+ cert_list = gnutls_certificate_get_peers(c->ssl_state.gnutls_session,
+ &cert_list_size);
+ if (!cert_list) {
+ gnutls_x509_crt_deinit(cert);
+ return 0;
+ }
+
+ if (gnutls_x509_crt_import(cert, &cert_list[0],
+ GNUTLS_X509_FMT_DER) != GNUTLS_E_SUCCESS) {
+ gnutls_x509_crt_deinit(cert);
+ return 0;
+ }
+
+ digest_size = sizeof(digest);
+ if (gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_SHA256, digest,
+ &digest_size)) {
+ gnutls_x509_crt_deinit(cert);
+ return 0;
+ }
+
+ gnutls_x509_crt_deinit(cert);
+#endif /* HAVE_LIBGNUTLS */
+
+ assert(c->ssl_state.fingerprint == NULL);
+
+ c->ssl_state.fingerprint = malloc(SHA256_STRING_LEN);
+ if (!c->ssl_state.fingerprint)
+ return 0;
+
+ for (i = 0; i < (int)digest_size; i++) {
+ c->ssl_state.fingerprint[i * 2] = hex[digest[i] / 16];
+ c->ssl_state.fingerprint[i * 2 + 1] = hex[digest[i] % 16];
+ }
+ c->ssl_state.fingerprint[i * 2] = '\0';
+
+ return 1;
+}