[Security-sig] Unified TLS API for Python
Wes Turner
wes.turner at gmail.com
Thu Jan 12 00:36:21 EST 2017
On Wednesday, January 11, 2017, Christian Heimes <christian at cheimes.de>
wrote:
On 2017-01-11 20:01, Cory Benfield wrote:
>
> > The ``Context`` abstract base class defines an object that allows
> configuration
> > of TLS. It can be thought of as a factory for ``TLSWrappedSocket`` and
> > ``TLSWrappedBuffer`` objects.
> >
> > The ``Context`` abstract base class has the following class definition::
> >
> > TLSBufferObject = Union[TLSWrappedSocket, TLSWrappedBuffer]
> > ServerNameCallback = Callable[[TLSBufferObject, Optional[str],
> Context], Any]
> >
> > class _BaseContext(metaclass=ABCMeta):
> >
> > @property
> > @abstractmethod
> > def validate_certificates(self) -> bool:
> > """
> > Whether to validate the TLS certificates. This switch
> operates at a
> > very broad scope: either validation is enabled, in which
> case all
> > forms of validation are performed including hostname
> validation if
> > possible, or validation is disabled, in which case no
> validation is
> > performed.
> >
> > Not all backends support having their certificate validation
> > disabled. If a backend does not support having their
> certificate
> > validation disabled, attempting to set this property to
> ``False``
> > will throw a ``TLSError``.
> > """
> >
> > @validate_certificates.setter
> > @abstractmethod
> > def validate_certificates(self, val: bool) -> None:
> > pass
>
>
> For 3.7 I'm planning to replace ssl.match_hostname() with OpenSSL
> 1.0.2's API. For now the one flag is enough. Later we can discuss
> settings for wildcard, IP address and CN matching.
>
> >
> > @abstractmethod
> > def register_certificates(self,
> > certificates: str,
> > key=None: Optional[str],
> > password=None: Optional[Callable[[],
> Union[AnyStr, bytearray]]]) -> None:
> > """
> > Loads a certificate, a number of intermediate certificates,
> and the
> > corresponding private key. These certificates will be
> offered to
> > the remote peer during the handshake if required.
> >
> > The ``certificates`` argument must be a bytestring
> containing the
> > PEM-encoded certificates. The first PEM-encoded certificate
> must be
> > the leaf certificate. All subsequence certificates will be
> offered
> > as intermediate additional certificates.
> >
> > The ``key`` argument, if present, must contain the
> PEM-encoded
> > private key associated with the leaf certificate. If not
> present,
> > the private key will be extracted from ``certificates``.
> >
> > The ``password`` argument may be a function to call to get
> the
> > password for decrypting the private key. It will only be
> called if
> > the private key is encrypted and a password is necessary. It
> will
> > be called with no arguments, and it should return a string,
> bytes,
> > or bytearray. If the return value is a string it will be
> encoded as
> > UTF-8 before using it to decrypt the key. Alternatively a
> string,
> > bytes, or bytearray value may be supplied directly as the
> password
> > argument. It will be ignored if the private key is not
> encrypted
> > and no password is needed.
> > """
>
> I don't think this function works for all libraries and use cases. For
> some implementations the order of certificates is very important. For
> NSS and PKCS#11 we rather need to specify the slot or nick name of the
> cert. For 3.7 I also like to introduce X509 objects and EVP_Key wrapper,
> so this function would need to consume a stack of certificates.
>
> Since this function is only required for TLS servers and TLS client cert
> authentication, I'd rather mark this function provisional or not define
> it in the first version.
>
>
>
This may be a bit of a different use case (and possibly worth having in the
first version of a new tls module):
"Hitless TLS Certificate Rotation in Go"
https://diogomonica.com/2017/01/11/hitless-tls-certificate-rotation-in-go/
- Can/could this be done with only set_sni_callback ?
- VerifyPeerCertificate
https://github.com/golang/go/issues/16363
- https://github.com/golang/go/blob/release-branch.go1.8/
src/crypto/tls/common.go#L406
>
> > @abstractmethod
> > def set_ciphers(self, ciphers: List[Ciphers]) -> None:
> > """
> > Set the available ciphers for TLS connections created with
> this
> > context. ``ciphers`` should be a list of ciphers from the
> > ``Cipher`` registry. If none of the ``ciphers`` provided to
> this
> > object are supported or available, a ``TLSError`` will be
> raised.
> > """
>
> Implementors should initial context with sensible default settings,
> preferable system-wide settings. For example Fedora is currently
> implementing https://fedoraproject.org/wiki/Changes/CryptoPolicy for
> OpenSSL, NSS and GnuTLS.
>
>
>
> >
> > @abstractmethod
> > def set_inner_protocols(self, protocols: List[NextProtocol]) ->
> None:
> > """
> > Specify which protocols the socket should advertise as
> supported
> > during the TLS handshake. This may be advertised using
> either or
> > both of ALPN or NPN.
> >
> > ``protocols`` should be a list of acceptable protocols in
> the form
> > of ``NextProtocol`` objects, such as ``[H2, HTTP1]``,
> ordered by
> > preference. The selection of the protocol will happen during
> the
> > handshake, and will use whatever protocol negotiation
> mechanisms
> > are available and supported by both peers.
> >
> > If the TLS implementation doesn't support protocol
> negotiation,
> > this method will raise ``NotImplementedError``.
> > """
> >
> > @abstractmethod
> > def set_sni_callback(self, callback:
> Optional[ServerNameCallback]) -> None:
> > """
> > Register a callback function that will be called after the
> TLS
> > Client Hello handshake message has been received by the TLS
> server
> > when the TLS client specifies a server name indication.
> >
> > Only one callback can be set per ``Context``. If
> ``callback`` is
> > ``None`` then the callback is disabled. Calling this
> function a
> > subsequent time will disable the previously registered
> callback.
> >
> > The ``callback`` function will be called with three
> arguments: the
> > first will be the ``TLSBufferObject`` for the connection; the
> > second will be a string that represents the server name that
> the
> > client is intending to communicate (or ``None`` if the TLS
> Client
> > Hello does not contain a server name); and the third
> argument will
> > be the original ``Context``. The server name argument will
> be the
> > IDNA *decoded* server name.
> >
> > The ``callback`` must return ``None`` to allow negotiation to
> > continue. Other return values signal errors. Attempting to
> control
> > what error is signaled by the underlying TLS implementation
> is not
> > specified in this API, but is up to the concrete
> implementation to
> > handle.
> > """
> >
> > @abstractmethod
> > def set_version_range(self, lower_bound=None:
> Optional[TLSVersion],
> > upper_bound=None: Optional[TLSVersion]) ->
> None:
> > """
> > Set the minumum and maximum versions of TLS that should be
> allowed
> > on TLS connections made by this context.
> >
> > If present, ``lower_bound`` will set the lowest acceptable
> TLS
> > version. If present, ``upper_bound`` will set the highest
> > acceptable TLS version. If either argument is ``None``, this
> will
> > leave that bound unchanged.
> > """
>
So, with
```
class TLSVersion(Enum):
MINIMUM_SUPPORTED
SSLv2
SSLv3
TLSv1
TLSv1_1
TLSv1_2
TLSv1_3
MAXIMUM_SUPPORTED
```
What are the (signed?) integer values?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/security-sig/attachments/20170111/57acdef4/attachment-0001.html>
More information about the Security-SIG
mailing list