def load_cert_chain(self, certfile, keyfile=None, password=None): """ Load a private key and the corresponding certificate. The certfile string must be the path to a single file in PEM format containing the certificate as well as any number of CA certificates needed to establish the certificate's authenticity. The keyfile string, if present, must point to a file containing the private key in. The password parameter is not supported yet. """ if password is not None: raise NotImplementedError("password callback support not " "implemented yet") if certfile is not None: ret = _lib.wolfSSL_CTX_use_certificate_chain_file( self.native_object, t2b(certfile)) if ret != _SSL_SUCCESS: raise SSLError("Unnable to load certificate chain. Err %d"% ret) else: raise TypeError("certfile should be a valid filesystem path") if keyfile is not None: ret = _lib.wolfSSL_CTX_use_PrivateKey_file( self.native_object, t2b(keyfile), _SSL_FILETYPE_PEM) if ret != _SSL_SUCCESS: raise SSLError("Unnable to load private key. Err %d" % ret)
def load_verify_locations(self, cafile=None, capath=None, cadata=None): """ Load a set of "certification authority" (CA) certificates used to validate other peers' certificates when verify_mode is other than CERT_NONE. At least one of cafile or capath must be specified. The cafile string, if present, is the path to a file of concatenated CA certificates in PEM format. The capath string, if present, is the path to a directory containing several CA certificates in PEM format. """ if cafile is None and capath is None and cadata is None: raise TypeError("cafile, capath and cadata cannot be all omitted") if cafile is not None or capath is not None: ret = _lib.wolfSSL_CTX_load_verify_locations( self.native_object, t2b(cafile) if cafile else _ffi.NULL, t2b(capath) if capath else _ffi.NULL) if ret != _SSL_SUCCESS: raise SSLError("Unnable to load verify locations. Err %d" % ret) if cadata is not None: ret = _lib.wolfSSL_CTX_load_verify_buffer( self.native_object, t2b(cadata), len(cadata), _SSL_FILETYPE_PEM) if ret != _SSL_SUCCESS: raise SSLError("Unnable to load verify locations. Err %d" % ret)
def load_cert_chain(self, certfile, keyfile=None, password=None): """ Load a private key and the corresponding certificate. The certfile string must be the path to a single file in PEM format containing the certificate as well as any number of CA certificates needed to establish the certificate's authenticity. The keyfile string, if present, must point to a file containing the private key in. If you are using a key protected cert or key file, you must call set_passwd_cb before calling load_cert_chain because wolfSSL validates the provided file the first time it is loaded. wolfSSL does not support loading a certificate file that contains both the certificate AND private key. In this case, users should split them into two separate files and load using the certfile and keyfile parameters, respectively. """ if certfile is not None: ret = _lib.wolfSSL_CTX_use_certificate_chain_file( self.native_object, t2b(certfile)) if ret != _SSL_SUCCESS: raise SSLError("Unable to load certificate chain. E(%d)" % ret) else: raise TypeError("certfile should be a valid filesystem path") if keyfile is not None: ret = _lib.wolfSSL_CTX_use_PrivateKey_file(self.native_object, t2b(keyfile), _SSL_FILETYPE_PEM) if ret != _SSL_SUCCESS: raise SSLError("Unable to load private key. E(%d)" % ret)
def do_handshake(self, block=False): # pylint: disable=unused-argument """ Perform a TLS/SSL handshake. """ self._check_closed("do_handshake") self._check_connected() if self._server_side: ret = _lib.wolfSSL_accept(self.native_object) else: ret = _lib.wolfSSL_connect(self.native_object) if ret != _SSL_SUCCESS: err = _lib.wolfSSL_get_error(self.native_object, 0) if err == _SSL_ERROR_WANT_READ: raise SSLWantReadError() elif err == _SSL_ERROR_WANT_WRITE: raise SSLWantWriteError() else: eBuf = _ffi.new("char[80]") eStr = _ffi.string(_lib.wolfSSL_ERR_error_string( err, eBuf)).decode("ascii") if 'ASN no signer error to confirm' in eStr or err is -188: # Some Python ssl consumers explicitly check error message # for 'certificate verify failed' raise SSLError("do_handshake failed with error %d, " "certificate verify failed" % err) # get alert code and string to put in exception msg alertHistoryPtr = _ffi.new("WOLFSSL_ALERT_HISTORY*") alertRet = _lib.wolfSSL_get_alert_history( self.native_object, alertHistoryPtr) if alertRet == _SSL_SUCCESS: alertHistory = alertHistoryPtr[0] code = alertHistory.last_rx.code alertDesc = _lib.wolfSSL_alert_type_string_long(code) if alertDesc != _ffi.NULL: alertStr = _ffi.string(alertDesc).decode("ascii") else: alertStr = '' raise SSLError("do_handshake failed with error %d: %s. " "alert (%d): %s" % (err, eStr, code, alertStr)) else: raise SSLError("do_handshake failed with error %d: %s" % (err, eStr))
def __init__(self, protocol, server_side=False): method = _WolfSSLMethod(protocol, server_side) self.protocol = protocol self._side = server_side self._verify_mode = None self.native_object = _lib.wolfSSL_CTX_new(method.native_object) # wolfSSL_CTX_new() takes ownership of the method. # the method is freed later inside wolfSSL_CTX_free() # or if wolfSSL_CTX_new() failed to allocate the context object. method.native_object = _ffi.NULL if self.native_object == _ffi.NULL: raise MemoryError("Unnable to allocate context object") # verify_mode initialization needs a valid native_object. self.verify_mode = CERT_NONE if not server_side: for curve in _SUPPORTED_CURVES: ret = _lib.wolfSSL_CTX_UseSupportedCurve(self.native_object, curve) if ret != _SSL_SUCCESS: raise SSLError("unnable to set curve (%d)" % curve)
def recv_into(self, buffer, nbytes=None, flags=0): """ Read nbytes bytes and place into buffer. If nbytes is 0, read up to full size of buffer. """ self._check_closed("read") self._check_connected() if buffer is None: raise ValueError("buffer cannot be None") if nbytes is None: nbytes = len(buffer) else: nbytes = min(len(buffer), nbytes) if nbytes == 0: return 0 data = _ffi.from_buffer(buffer) length = _lib.wolfSSL_read(self.native_object, data, nbytes) if length < 0: err = _lib.wolfSSL_get_error(self.native_object, 0) if err == _SSL_ERROR_WANT_READ: raise SSLWantReadError() else: raise SSLError("wolfSSL_read error (%d)" % err) return length
def do_handshake(self, block=False): """ Perform a TLS/SSL handshake. """ self._check_closed("do_handshake") self._check_connected() ret = _lib.wolfSSL_negotiate(self.native_object) if ret != _SSL_SUCCESS: raise SSLError("do_handshake failed with error %d" % ret)
def set_ciphers(self, ciphers): """ Set the available ciphers for sockets created with this context. It should be a string in the wolfSSL cipher list format. If no cipher can be selected (because compile-time options or other configuration forbids use of all the specified ciphers), an SSLError will be raised. """ ret = _lib.wolfSSL_CTX_set_cipher_list(self.native_object, t2b(ciphers)) if ret != _SSL_SUCCESS: raise SSLError("Unnable to set cipher list")
def use_sni(self, server_hostname): """ Sets the SNI hostname, wraps native wolfSSL_UseSNI() """ sni = t2b(server_hostname) ret = _lib.wolfSSL_UseSNI(self.native_object, 0, sni, len(sni)) if ret != _SSL_SUCCESS: raise SSLError("Unable to set wolfSSL SNI")
def sendall(self, data, flags=0): if flags != 0: raise NotImplementedError("non-zero flags not allowed in calls to " "sendall() on %s" % self.__class__) length = len(data) sent = 0 while sent < length: ret = self.write(data[sent:]) if (ret < 0): err = _lib.wolfSSL_get_error(self.native_object, 0) if err == _SSL_ERROR_WANT_WRITE: raise SSLWantWriteError() else: raise SSLError("wolfSSL_write error (%d)" % err) sent += ret return None
def read(self, length=1024, buffer=None): """ Read up to LENGTH bytes and return them. Return zero-length string on EOF. """ self._check_closed("read") self._check_connected() if buffer is not None: raise ValueError("buffer not allowed in calls to " "read() on %s" % self.__class__) data = _ffi.new('byte[%d]' % length) length = _lib.wolfSSL_read(self.native_object, data, length) if length < 0: err = _lib.wolfSSL_get_error(self.native_object, 0) if err == _SSL_ERROR_WANT_READ: raise SSLWantReadError() else: raise SSLError("wolfSSL_read error (%d)" % err) return _ffi.buffer(data, length)[:] if length > 0 else b''
def __init__(self, session): self.native_object = _lib.wolfSSL_get_peer_certificate(session) if self.native_object == _ffi.NULL: raise SSLError("Unable to get internal WOLFSSL_X509 from wolfSSL")