[gnutls-help] HPKH style (pin-sha256) peer verification in gnutls_certificate_verify_function callback

Ondřej Surý ondrej at sury.org
Mon Jul 18 23:20:34 CEST 2016


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ý <ondrej at sury.org>
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
> 



More information about the Gnutls-help mailing list