Nikos, thanks for the tips, I ended up using gnutls_certificate_get_peers and iterating the list with gnutls_x509_crt_import.
JFTR the full implementation starts here: https://gitlab.labs.nic.cz/labs/knot/blob/dns-over-tls/src/utils/common/netio.c#L262 and looks like this: if (gnutls_certificate_type_get(session) != GNUTLS_CRT_X509) { \ ERR("Invalid certificate type\n"); return GNUTLS_E_CERTIFICATE_ERROR; } raw_certificate_list = gnutls_certificate_get_peers(session, &raw_certificate_list_size); if (raw_certificate_list == NULL || raw_certificate_list_size == 0) { ERR("Certificate list is empty\n"); return GNUTLS_E_NO_CERTIFICATE_FOUND; } uint8_t sha256[64] = { 0 }; size_t sha256_len; for (int i = 0; i < raw_certificate_list_size; i++) { ret = gnutls_x509_crt_init(&certificate); if (ret < 0) { return ret; } ret = gnutls_x509_crt_import(certificate, &raw_certificate_list[i], GNUTLS_X509_FMT_DER); if (ret < 0) { gnutls_x509_crt_deinit(certificate); return ret; } sha256_len = sizeof(sha256); ret = gnutls_x509_crt_get_key_id(certificate, GNUTLS_KEYID_USE_SHA256, sha256, &sha256_len); if (ret < 0) { gnutls_x509_crt_deinit(certificate); return ret; } if (memcmp(sha256, pin, sha256_len) == 0) { pin_seen = 1; INFO("Matched certificate using pin-sha256=\"%s\"\n", value); } gnutls_x509_crt_deinit(certificate); } And this is inside the verify_certificate callback function. The TOFU is not really usable here, but the next thing I might look into is DANE authentication (https://datatracker.ietf.org/doc/draft-ietf-dprive-dtls-and-tls-profiles/?include_text=1 Section 9.2) As a side note, I am really impress with the ease I was able to start implementing things in gnutls, especially the clarity of the API and the documentation. Really great job! Cheers, -- Ondřej Surý <[email protected]> Knot DNS (https://www.knot-dns.cz/) – a high-performance DNS server Knot Resolver (https://www.knot-resolver.cz/) – secure, privacy-aware, fast DNS(SEC) resolver Vše pro chleba (https://vseprochleba.cz) – Potřeby pro pečení chleba všeho druhu On Mon, Jul 18, 2016, at 21:26, Nikos Mavrogiannopoulos wrote: > On Sun, 2016-07-17 at 22:49 +0200, Ondřej Surý wrote: > > Hey, > > > > during the IETF hackathon I implemented DNS over TLS (RFC 7858) for > > kdig > > utility in Knot DNS[1] and now I am implementing the different TLS > > Privacy Profiles (Section 4). > > > > Using the excellent examples and documentation[*] I was able to > > implement: > > > > - Opportunistic Privacy Profile (just return 0) > > - hostname verification with system ca-file > > - custom ca-file > > > > and now I would like to implement verification of pin-sha256 > > user-provided values. Could you please guide me to a place where I > > should start looking? Is there already some other program that > > implemented HSTS/HPKP using GnuTLS? > > And if not than a pointer to > > documentation for SPKI retrieval would be nice (not quite sure > > https://www.gnutls.org/manual/html_node/X509-certificate-API.html is > > the > > right place and what function am I looking for). > > If what you want to is to obtain the DER SPKI format you can import the > certificate to gnutls_pubkey_t structure and export that one to get > the DER SPKI. The gnutls_pubkey_import_x509_raw() is the function you > most likely neeed. > > Not sure if it is related to your use case, but there is the trust on > first use API which can be used to pin certificates and keys > (i.e., gnutls_store_pubkey and gnutls_verify_stored_pubkey). > > regards, > Nikos > _______________________________________________ Gnutls-help mailing list [email protected] http://lists.gnupg.org/mailman/listinfo/gnutls-help
