Date: Mon, 23 Mar 2020 12:54:52 +0100 From: Joakim Sindholt <opensource@...sha.com> To: tlsify@...ts.openwall.com Subject: Interface design considerations Yesterday we (Rich and I) had a discussion about the public interface of tlsify, taking the first step towards a working, deployable product. Rich suggested taking it to the list and I agree, so here are the notes: Foreword: Priority 1 should be designing a solid API that will allow new, as well as existing software to adopt tlsify instead of linking in a library. As a note to this I, if there are no objections, will be working on an actual implementation of what's being discussed as I fear we will otherwise devolve into one of those "we just publish a spec so other people can implement it" groups. I also believe we must eventually publish a high quality implementation or the project will not be taken seriously as it is a significant departure from what's normally considered high performance. (1) Known protocol-specific requirements My own needs are mostly JSON over HTTPS based and as such come with relatively well-known requirements: * Transparent handshake and encryption. * The ability to specify a CA certificate or a set of CA certificates for services with their own PKI. * The ability to specify a client certificate static to the host connected to. Rich has recently worked on encrypted email transport, leading into DANE and would also like tlsify to: * Use DANE transparently. DANE could either be implemented as a function of existing infrastructure on the host system or done entirely within tlsify. The former is nice both from a size perspective but also seems architecturally more sound. The latter might be necessary as the infrastructure is rarely present on systems and require some pretty invasive changes if not; that complicates testing (and adoption!) DANE has 4 modes (this will be useful later): 0/PKIX-TA Specify an existing CA certificate that the presented certificate must validate through. 1/PKIX-EE Specify a certificate that must match the presented one perfectly in addition to validating through an existing CA. 2/DANE-TA Specify a certificate which the presented one must validate through without the requirement of it also validating to an existing CA. 3/DANE-EE Specify a self signed certificate that must match the presented one exactly. There are protocol specific requirements for how the validation is done. For example: HTTP requires that in all cases the CN of the presented certificate matches the domain name that was connected to while SMTP doesn't require a CN match for DANE-EE specifically. It should do every validation pass under the sun by default. The API should be that you may turn some checks off explicitly. The CN will still be needed for SNI, so just not specifying it isn't an option. Furthermore you might want to specify a CN for validation but NOT use SNI. It's probably unnecessary to have a back-and-forth with the host process. We discussed basing the validation API on DANE, so perhaps an option that allows you to specify for what cases of DANE the CN matching should be turned off, eg. -x DANE-EE and -x * for turning it off altogether. (2) Using a different set of CAs than the system trust store Useful in cases where you have your own PKI. I have multiple cases of service providers using their own CA certificates that are not and should not be part of the system-wide trust store. My suggestion was to allow an option, say -C /path/to/ca, that specified a directory of or a single file containing CA certificates to validate against. Rich suggested modeling the API on DANE, where the options are based on DANE types, eg. -C DANE-TA /path/to/ca.crt, with the ability to specify multiple just like real DANE logically ||'ing them. FWIW I like Rich's idea much better than my own. Rich is concerned that it's not sufficiently general but also notes that it constitutes a good default model. I agree. (3) Option format We both agree that tlsify should take arguments in the traditional getopt style with single character options. I suggested that the basic format ought to be: tlsify <ifd[,ofd]> <cn> tlsify 3,4 host.tld tlsify 7 host.tls where you can specify either a pair of pipes or a single socket that will be used for TLS communication, with cleartext being received and sent over fds 0 and 1 respectively. Rich suggested a more cautious approach where all options are provided as getopt options, eg: tlsify [-f ifd[,ofd]] [-n cn] This has the benefit of not locking tlsify into any specific usage pattern. I believe that the fd or fd pair is so fundamental to tlsify that it shouldn't require an option. The only reason for leaving it out appears to be to let tlsify establish the connection itself. The CN should probably be an option. It's uncertain as to whether leaving out the CN should turn off CN validation, as it might just be accidentally left out during development and never produce an issue aside from possibly severely compromising security. Turning off SNI silently sounds fine to me. We both tentatively agree that there's no point in allowing for overriding the cleartext fds as it can seemingly at best save a dup2 call. (4) Error channel There needs to be a way of communicating the error back to the host process. If nothing else then just to display it to the user. I, in spite of disliking the idea, suggested that you could use exit codes to tell the host what the issue was. Rich suggested that what you really want is a detailed error description, eg.: "server presented a certificate for musl.libc.org not for ewontfix.com" As a proponent of error strings I don't have a problem with an approach that just sends literal strings over an optional fd back to the host to read but it's uncertain whether that's good enough. There's also the issue of translating error strings which I'm personally happy to forego but others might not be. Some things that also warrant further discussion: * Specifying a set of acceptable TLS versions, key exchange algorithms and ciphers. * Having tlsify do the connecting for you. - I disagree with this. IMO it's unrelated to TLS and a feature-creep springboard for even more TLS-unrelated functionality. * Specifying a client certificate. - Rich thinks "some degree of protocol is needed to make it meaningful." * How to specify ALPN and how to communicate to the host process what was chosen. What I propose so far: tlsify [options] fd[,fd] If only 1 fd is specified it's both the TLS input and output fd. If 2 are specified they're the TLS input and output fds respectively. -n cn Specify a common name for use in validation and SNI. -C dane-type path-to-file-or-dir Act as a DANE record of the specified type, with the data being pulled from the file or all files in the folder. This also deactivates the fetching of DANE records and the use of the default system trust store excepting dane-type=PKIX-*. -x dane-type Turn off CN validation for a given DANE record type. -x CN Turn off CN validation altogether. -x SNI Turn off SNI. and tentatively: -c path-to-file Specify a client certificate. And I think that covers all of it.
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.