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

Reply via email to