diff --git a/clientutil/tls.go b/clientutil/tls.go
new file mode 100644
index 0000000000000000000000000000000000000000..6eb0749eb78cd75cedb4168626ff67536387e9de
--- /dev/null
+++ b/clientutil/tls.go
@@ -0,0 +1,37 @@
+package clientutil
+
+import (
+	"crypto/tls"
+
+	common "git.autistici.org/ai3/go-common"
+)
+
+// TLSClientConfig defines the TLS parameters for a client connection
+// that should use a client X509 certificate for authentication.
+type TLSClientConfig struct {
+	Cert string `yaml:"cert"`
+	Key  string `yaml:"key"`
+	CA   string `yaml:"ca"`
+}
+
+// TLSConfig returns a tls.Config object with the current configuration.
+func (c *TLSClientConfig) TLSConfig() (*tls.Config, error) {
+	cert, err := tls.LoadX509KeyPair(c.Cert, c.Key)
+	if err != nil {
+		return nil, err
+	}
+	tlsConf := &tls.Config{
+		Certificates: []tls.Certificate{cert},
+	}
+
+	if c.CA != "" {
+		cas, err := common.LoadCA(c.CA)
+		if err != nil {
+			return nil, err
+		}
+		tlsConf.RootCAs = cas
+	}
+	tlsConf.BuildNameToCertificate()
+
+	return tlsConf, nil
+}
diff --git a/misc.go b/misc.go
new file mode 100644
index 0000000000000000000000000000000000000000..582af3f7e148988ff382d50e9a2e0e1e9e0894d2
--- /dev/null
+++ b/misc.go
@@ -0,0 +1,17 @@
+package common
+
+import (
+	"crypto/x509"
+	"io/ioutil"
+)
+
+// LoadCA loads a file containing CA certificates into a x509.CertPool.
+func LoadCA(path string) (*x509.CertPool, error) {
+	data, err := ioutil.ReadFile(path)
+	if err != nil {
+		return nil, err
+	}
+	cas := x509.NewCertPool()
+	cas.AppendCertsFromPEM(data)
+	return cas, nil
+}