GnuTLSExternalValidation¶
This page is intended to flesh out ideas to externalize the X.509 chain validation, X.509 private key handling, and possibly also OpenPGP validation and private key handling.
It is important to realize that these are different problems, so the solution may be different. Let's first make the goals clear:
- Make it possible to store private keys in a process different from the process that runs the GnuTLS client/server.
- Make it possible to perform X.509 chain validation in a different process.
- Make it possible to perform OpenPGP key validation in a different process.
One must decide whether the external agent should be responsible for making authentication decisions, authorization decisions, or both. Possibly it should be able to make both kind of decisions. The GnuTLS process can always make further authorization decisions as well.
For private keys, there is the PKCS#11 interface. GnuTLS has a branch that supports it. However, PKCS#11 doesn't solve the problem with an external process. It seems better to move the PKCS#11 interface to the external agent, rather than adding PKCS#11 interface to GnuTLS itself. Btw, GnuTLS already has PKCS#11 support on a special branch, and has been tested against the Scute PKCS#11 provider together with a Swedish eID X.509 smartcard.
The solution should allow simple integration with GNOME components such as SeaHorse.
Private key protocol¶
Possible we should re-use GnuPG's external protocol here? What we need is an IPC protocol that does:
SIGN [ALG] [KEY-ID] [TLS-DATA]
Where KEY-ID somehow denotes a key to use, and TLS-DATA is the data that needs to be signed using the TLS algorithm. Given that TLS supports several algorithms, and even RSA is supported in more than one mode, there needs to be an ALG flag to indicate this.
X.509 Chain Validation¶
GnuPG's dirmngr has a protocol for doing this, using assuan. Unfortunately, assuan's design criteria state "no protection against DoS needed". This might make it unsuitable for a TLS implementation or other online tool.
It is not clear to me whether the trusted CAs should be sent over the IPC, or whether it is something that is assumed to be known by the agent. The latter seems safer, but the former may be useful in some scenarios. (what scenarios?) They aren't mutually incompatible, so maybe we can support both.
Thus we need a command to send over a trusted certificate:
TRUSTED [b64pem...]
And also send over untrusted certificates provided by the TLS peer:
UNTRUSTED [b64pem...]
Finally, a request to perform chain validation on a particular certificate is performed using:
VALIDATE [b64pem...]
Generic Certificate Validation¶
It would be nice to be able to hand the agent any kind of certificate (OpenPGP or X.509), or even to be able to hand the agent a raw public key to see if it validates.
The crucial request would be:
VALIDATE {LABEL} {CERTTYPE} {PEERNAME} {CERTIFICATE}
This says "I'm a program called LABEL. I'm about to send you a certificate of type CERTTYPE. I want you to tell me whether the specified PEERNAME matches one of the names stored in the certificate, and that the matching name in the certificate is cryptographically valid based on your knowledge of trusted certifiers."
The agent can respond with VALID or INVALID. We maybe should consider whether INVALID might be implemented as an extensible set of reasons for invalidity (e.g. EXPIRED, NOMATCH, UNTRUSTED, SELFSIGNED, etc): would the potential extensibility from this outweigh the added implementation and semantic complexity?
The possible options for CERTTYPE could be:
- RAWPUBKEY (maybe modelled after ssh-dss and ssh-rsa in RFC 4253 ?)
- OPENPGP (after section 11.1 of RFC 4880 either base-64 encoded or raw)
- X509 (after RFC 5280, either PEM or DER encoded)
This would allow numerous clients and servers to make use of the validation agent. For example:
- lsh could feed its fetched host keys to the validation agent instead of having to maintain ~/.lsh/host-acls
- slapd could use the validation agent to identify the DN of the remote client.
- subversion could ask the validation agent to ensure that the OpenPGP certificate offered by a remote https server (using mod_gnutls) is in fact who it claims to be (and the mod_gnutls could validate the identity of the client in the same way).
Additionally, it might be nice to have a command to offer intermediate certificates to the certificate store:
UNTRUSTED {LABEL} {CERTTYPE} {CERTIFICATE}
using UNTRUSTED with a RAWPUBKEY certificate wouldn't be a meaningful operation, but it could be used for intermediate X.509 certificates, or for the equivalent OpenPGP certificates (if such things were handy).