forked from wolfSSL/wolfssl
Merge pull request #683 from moisesguimaraes/wolfssl-py
wolfssl python wrapper
This commit is contained in:
23
certs/external/ca-digicert-ev.pem
vendored
Normal file
23
certs/external/ca-digicert-ev.pem
vendored
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs
|
||||||
|
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
|
||||||
|
d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
|
||||||
|
ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL
|
||||||
|
MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
|
||||||
|
LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
|
||||||
|
RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm
|
||||||
|
+9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW
|
||||||
|
PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM
|
||||||
|
xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB
|
||||||
|
Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3
|
||||||
|
hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg
|
||||||
|
EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF
|
||||||
|
MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA
|
||||||
|
FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec
|
||||||
|
nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z
|
||||||
|
eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF
|
||||||
|
hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2
|
||||||
|
Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
|
||||||
|
vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep
|
||||||
|
+OkuE6N36B9K
|
||||||
|
-----END CERTIFICATE-----
|
@@ -3,6 +3,7 @@
|
|||||||
# All paths should be given relative to the root
|
# All paths should be given relative to the root
|
||||||
|
|
||||||
include wrapper/python/wolfcrypt/include.am
|
include wrapper/python/wolfcrypt/include.am
|
||||||
|
include wrapper/python/wolfssl/include.am
|
||||||
|
|
||||||
# wolfSSL CSharp wrapper files
|
# wolfSSL CSharp wrapper files
|
||||||
EXTRA_DIST+= wrapper/CSharp/wolfSSL-DTLS-PSK-Server/App.config
|
EXTRA_DIST+= wrapper/CSharp/wolfSSL-DTLS-PSK-Server/App.config
|
||||||
|
3
wrapper/python/wolfcrypt/.gitignore
vendored
3
wrapper/python/wolfcrypt/.gitignore
vendored
@@ -13,3 +13,6 @@ dist/
|
|||||||
.tox/
|
.tox/
|
||||||
# Sphinx documentation
|
# Sphinx documentation
|
||||||
docs/_build/
|
docs/_build/
|
||||||
|
|
||||||
|
# Virtual env
|
||||||
|
.env
|
||||||
|
@@ -17,22 +17,20 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program; if not, write to the Free Software
|
# along with this program; if not, write to the Free Software
|
||||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
|
||||||
|
# pylint: disable=unused-import, undefined-variable
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
from binascii import hexlify as b2h, unhexlify as h2b
|
from binascii import hexlify as b2h, unhexlify as h2b
|
||||||
|
|
||||||
|
_PY3 = sys.version_info[0] == 3
|
||||||
|
_TEXT_TYPE = str if _PY3 else unicode
|
||||||
|
_BINARY_TYPE = bytes if _PY3 else str
|
||||||
|
|
||||||
if sys.version_info[0] == 3:
|
def t2b(string):
|
||||||
_text_type = str
|
|
||||||
_binary_type = bytes
|
|
||||||
else:
|
|
||||||
_text_type = unicode
|
|
||||||
_binary_type = str
|
|
||||||
|
|
||||||
|
|
||||||
def t2b(s):
|
|
||||||
"""
|
"""
|
||||||
Converts text to bynary.
|
Converts text to bynary.
|
||||||
"""
|
"""
|
||||||
if isinstance(s, _binary_type):
|
if isinstance(string, _BINARY_TYPE):
|
||||||
return s
|
return string
|
||||||
return _text_type(s).encode("utf-8")
|
return _TEXT_TYPE(string).encode("utf-8")
|
||||||
|
38
wrapper/python/wolfssl/.centos-provisioner.sh
Normal file
38
wrapper/python/wolfssl/.centos-provisioner.sh
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
[ "$(whoami)" != "root" ] && echo "Sorry, you are not root." && exit 1
|
||||||
|
|
||||||
|
rpm -ivh http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
|
||||||
|
|
||||||
|
yum install -y \
|
||||||
|
git autoconf libtool libffi-devel python-devel python34-devel python2-pip
|
||||||
|
|
||||||
|
pip install -U pip setuptools
|
||||||
|
|
||||||
|
git clone --depth 1 https://github.com/wolfssl/wolfssl.git
|
||||||
|
[ $? -ne 0 ] && echo "\n\nCouldn't download wolfssl.\n\n" && exit 1
|
||||||
|
|
||||||
|
pushd wolfssl
|
||||||
|
|
||||||
|
./autogen.sh
|
||||||
|
./configure
|
||||||
|
make
|
||||||
|
make install
|
||||||
|
echo /usr/local/lib > wolfssl.conf
|
||||||
|
mv wolfssl.conf /etc/ld.so.conf
|
||||||
|
ldconfig
|
||||||
|
|
||||||
|
popd
|
||||||
|
|
||||||
|
rm -rf wolfssl
|
||||||
|
|
||||||
|
pushd /vagrant
|
||||||
|
|
||||||
|
pip install -r requirements-testing.txt
|
||||||
|
|
||||||
|
make clean
|
||||||
|
|
||||||
|
tox -epy27,py34 -- -v
|
||||||
|
|
||||||
|
popd
|
||||||
|
|
||||||
|
# pip install wolfssl
|
||||||
|
# [ $? -ne 0 ] && echo "\n\nCouldn't install wolfssl.\n\n" && exit 1
|
21
wrapper/python/wolfssl/.gitignore
vendored
Normal file
21
wrapper/python/wolfssl/.gitignore
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# Distribution
|
||||||
|
build/
|
||||||
|
dist/
|
||||||
|
.eggs/
|
||||||
|
*.egg-info/
|
||||||
|
|
||||||
|
# Unit test
|
||||||
|
.tox/
|
||||||
|
htmlcov/
|
||||||
|
.coverage
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# Certificates
|
||||||
|
certs/
|
36
wrapper/python/wolfssl/.ubuntu-provisioner.sh
Normal file
36
wrapper/python/wolfssl/.ubuntu-provisioner.sh
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
[ "$(whoami)" != "root" ] && echo "Sorry, you are not root." && exit 1
|
||||||
|
|
||||||
|
apt-get update
|
||||||
|
|
||||||
|
apt-get install -y \
|
||||||
|
git autoconf libtool python-dev python3-dev python-pip libffi-dev
|
||||||
|
|
||||||
|
pip install -U pip setuptools
|
||||||
|
|
||||||
|
git clone --depth 1 https://github.com/wolfssl/wolfssl.git
|
||||||
|
[ $? -ne 0 ] && echo "\n\nCouldn't download wolfssl.\n\n" && exit 1
|
||||||
|
|
||||||
|
pushd wolfssl
|
||||||
|
|
||||||
|
./autogen.sh
|
||||||
|
./configure
|
||||||
|
make
|
||||||
|
make install
|
||||||
|
ldconfig
|
||||||
|
|
||||||
|
popd
|
||||||
|
|
||||||
|
rm -rf wolfssl
|
||||||
|
|
||||||
|
pushd /vagrant
|
||||||
|
|
||||||
|
pip install -r requirements-testing.txt
|
||||||
|
|
||||||
|
make clean
|
||||||
|
|
||||||
|
tox -epy27,py34 -- -v
|
||||||
|
|
||||||
|
popd
|
||||||
|
|
||||||
|
# pip install wolfssl
|
||||||
|
# [ $? -ne 0 ] && echo -e "\n\nCouldn't install wolfssl.\n\n" && exit 1
|
23
wrapper/python/wolfssl/LICENSING.rst
Normal file
23
wrapper/python/wolfssl/LICENSING.rst
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
Licensing
|
||||||
|
=========
|
||||||
|
|
||||||
|
wolfSSL’s software is available under two distinct licensing models:
|
||||||
|
open source and standard commercial licensing. Please see the relevant
|
||||||
|
section below for information on each type of license.
|
||||||
|
|
||||||
|
Open Source
|
||||||
|
-----------
|
||||||
|
|
||||||
|
wolfCrypt and wolfSSL software are free software downloads and may be modified
|
||||||
|
to the needs of the user as long as the user adheres to version two of the GPL
|
||||||
|
License. The GPLv2 license can be found on the `gnu.org website
|
||||||
|
<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>`_.
|
||||||
|
|
||||||
|
Commercial Licensing
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
Businesses and enterprises who wish to incorporate wolfSSL products into
|
||||||
|
proprietary appliances or other commercial software products for
|
||||||
|
re-distribution must license commercial versions. Licenses are generally
|
||||||
|
issued for one product and include unlimited royalty-free distribution.
|
||||||
|
Custom licensing terms are also available at licensing@wolfssl.com.
|
2
wrapper/python/wolfssl/MANIFEST.in
Normal file
2
wrapper/python/wolfssl/MANIFEST.in
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
include LICENSING.rst
|
||||||
|
recursive-include certs *.pem
|
58
wrapper/python/wolfssl/Makefile
Normal file
58
wrapper/python/wolfssl/Makefile
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
# Makefile
|
||||||
|
#
|
||||||
|
# Copyright (C) 2006-2017 wolfSSL Inc.
|
||||||
|
#
|
||||||
|
# This file is part of wolfSSL. (formerly known as CyaSSL)
|
||||||
|
#
|
||||||
|
# wolfSSL is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# wolfSSL is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
|
||||||
|
.PHONY : all clean clean-test clean-build clean-pyc install test check upload
|
||||||
|
|
||||||
|
# builds the module
|
||||||
|
all :
|
||||||
|
python ./setup.py build
|
||||||
|
|
||||||
|
#builds and installs the module
|
||||||
|
install : all
|
||||||
|
python ./setup.py install
|
||||||
|
|
||||||
|
## removes all build, test, coverage and Python artifacts
|
||||||
|
clean : clean-test clean-build clean-pyc
|
||||||
|
|
||||||
|
## removes test and coverage artifacts
|
||||||
|
clean-test :
|
||||||
|
rm -rf .coverage .tox/ htmlcov/
|
||||||
|
|
||||||
|
## removes build artifacts
|
||||||
|
clean-build :
|
||||||
|
rm -rf build/ dist/ .eggs/
|
||||||
|
find . -name '*.egg-info' -exec rm -rf {} +
|
||||||
|
find . -name '*.egg' -exec rm -v {} +
|
||||||
|
|
||||||
|
## removes Python file artifacts
|
||||||
|
clean-pyc :
|
||||||
|
find src test -name '__pycache__' -exec rm -rf {} +
|
||||||
|
find src test -name '*.pyc' -exec rm -f {} +
|
||||||
|
find src test -name '*.pyo' -exec rm -f {} +
|
||||||
|
|
||||||
|
# runs unit tests
|
||||||
|
check : test
|
||||||
|
|
||||||
|
test : clean-pyc
|
||||||
|
tox
|
||||||
|
|
||||||
|
# publishes module at pypi
|
||||||
|
upload : test
|
||||||
|
python ./setup.py sdist upload
|
96
wrapper/python/wolfssl/README.rst
Normal file
96
wrapper/python/wolfssl/README.rst
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
Welcome
|
||||||
|
=======
|
||||||
|
|
||||||
|
``wolfssl Python`` is a Python module that encapsulates ``wolfssl C``, a `lightweight C-language-based SSL/TLS library <https://wolfssl.com/wolfSSL/Products-wolfssl.html>`_ targeted for embedded, RTOS, or
|
||||||
|
resource-constrained environments primarily because of its small size, speed,
|
||||||
|
and portability.
|
||||||
|
|
||||||
|
Installation
|
||||||
|
============
|
||||||
|
|
||||||
|
In order to use ``wolfssl Python``, you'll also need to install ``wolfssl C``.
|
||||||
|
|
||||||
|
Mac OSX
|
||||||
|
-------
|
||||||
|
|
||||||
|
Installing from ``homebrew`` and ``pip`` package managers:
|
||||||
|
|
||||||
|
.. code-block:: shell
|
||||||
|
|
||||||
|
# wolfssl C installation
|
||||||
|
brew install wolfssl
|
||||||
|
|
||||||
|
# wolfssl Python installation
|
||||||
|
sudo -H pip install wolfssl
|
||||||
|
|
||||||
|
Installing from ``source code``:
|
||||||
|
|
||||||
|
.. code-block:: shell
|
||||||
|
|
||||||
|
# wolfssl C installation
|
||||||
|
git clone https://github.com/wolfssl/wolfssl.git
|
||||||
|
cd wolfssl/
|
||||||
|
./autogen.sh
|
||||||
|
./configure --enable-sha512
|
||||||
|
make
|
||||||
|
sudo make install
|
||||||
|
|
||||||
|
# wolfssl Python installation
|
||||||
|
cd wrapper/python/wolfssl
|
||||||
|
sudo make install
|
||||||
|
|
||||||
|
|
||||||
|
Linux
|
||||||
|
-----
|
||||||
|
|
||||||
|
.. code-block:: shell
|
||||||
|
|
||||||
|
# dependencies installation
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y git autoconf libtool
|
||||||
|
sudo apt-get install -y python-dev python3-dev python-pip libffi-dev
|
||||||
|
|
||||||
|
# wolfssl C installation
|
||||||
|
git clone https://github.com/wolfssl/wolfssl.git
|
||||||
|
cd wolfssl/
|
||||||
|
./autogen.sh
|
||||||
|
./configure --enable-sha512
|
||||||
|
make
|
||||||
|
sudo make install
|
||||||
|
|
||||||
|
sudo ldconfig
|
||||||
|
|
||||||
|
# wolfssl Python installation
|
||||||
|
sudo -H pip install wolfssl
|
||||||
|
|
||||||
|
|
||||||
|
Testing
|
||||||
|
=======
|
||||||
|
|
||||||
|
To run the tox tests in the source code, you'll need ``tox`` and a few other
|
||||||
|
requirements. The source code relies at **WOLFSSL_DIR/wrapper/python/wolfssl**
|
||||||
|
where **WOLFSSL_DIR** is the path of ``wolfssl C``'s source code.
|
||||||
|
|
||||||
|
1. Make sure that the testing requirements are installed:
|
||||||
|
|
||||||
|
.. code-block:: shell
|
||||||
|
|
||||||
|
sudo -H pip install -r requirements-testing.txt
|
||||||
|
|
||||||
|
|
||||||
|
2. Run ``make check``:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ make check
|
||||||
|
...
|
||||||
|
_________________________________ summary _________________________________
|
||||||
|
py27: commands succeeded
|
||||||
|
SKIPPED: py34: InterpreterNotFound: python3.4
|
||||||
|
py35: commands succeeded
|
||||||
|
py36: commands succeeded
|
||||||
|
congratulations :)
|
||||||
|
|
||||||
|
Note: the test is performed using multiple versions of python. If you are
|
||||||
|
missing a version the test will be skipped with an **InterpreterNotFound
|
||||||
|
error**.
|
17
wrapper/python/wolfssl/Vagrantfile
vendored
Normal file
17
wrapper/python/wolfssl/Vagrantfile
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
# -*- mode: ruby -*-
|
||||||
|
# vi: set ft=ruby :
|
||||||
|
VAGRANTFILE_API_VERSION = "2"
|
||||||
|
|
||||||
|
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
||||||
|
|
||||||
|
config.vm.define "default" do |default|
|
||||||
|
default.vm.box = "ubuntu/trusty64"
|
||||||
|
default.vm.provision "shell", path: ".ubuntu-provisioner.sh"
|
||||||
|
end
|
||||||
|
|
||||||
|
config.vm.define "centos", autostart: false do |centos|
|
||||||
|
centos.vm.box = "moisesguimaraes/centos72-64"
|
||||||
|
centos.vm.provision "shell", path: ".centos-provisioner.sh"
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
59
wrapper/python/wolfssl/docs/Makefile
Normal file
59
wrapper/python/wolfssl/docs/Makefile
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
# Makefile
|
||||||
|
#
|
||||||
|
# Copyright (C) 2006-2017 wolfSSL Inc.
|
||||||
|
#
|
||||||
|
# This file is part of wolfSSL. (formerly known as CyaSSL)
|
||||||
|
#
|
||||||
|
# wolfSSL is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# wolfSSL is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
|
||||||
|
.PHONY : all clean html pdf man
|
||||||
|
|
||||||
|
# You can set these variables from the command line.
|
||||||
|
SPHINXOPTS =
|
||||||
|
SPHINXBUILD = sphinx-build
|
||||||
|
PAPER = a4
|
||||||
|
BUILDDIR = _build
|
||||||
|
|
||||||
|
# Internal variables.
|
||||||
|
PAPEROPT_a4 = -D latex_paper_size=a4
|
||||||
|
PAPEROPT_letter = -D latex_paper_size=letter
|
||||||
|
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
|
||||||
|
|
||||||
|
all:
|
||||||
|
@echo "Please use \`make <target>' where <target> is one of"
|
||||||
|
@echo " html to make a single large HTML file"
|
||||||
|
@echo " pdf to make LaTeX files and run them through pdflatex"
|
||||||
|
@echo " man to make manual pages"
|
||||||
|
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
|
||||||
|
@echo " coverage to run coverage check of the documentation (if enabled)"
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(BUILDDIR)/*
|
||||||
|
|
||||||
|
html:
|
||||||
|
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
|
||||||
|
|
||||||
|
pdf:
|
||||||
|
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||||
|
@echo "Running LaTeX files through pdflatex..."
|
||||||
|
$(MAKE) -C $(BUILDDIR)/latex all-pdf
|
||||||
|
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
|
||||||
|
|
||||||
|
man:
|
||||||
|
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
|
21
wrapper/python/wolfssl/docs/api.rst
Normal file
21
wrapper/python/wolfssl/docs/api.rst
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
API Documentation
|
||||||
|
=================
|
||||||
|
|
||||||
|
.. module:: wolfssl
|
||||||
|
|
||||||
|
wrap_socket
|
||||||
|
-----------
|
||||||
|
|
||||||
|
.. autofunction:: wrap_socket
|
||||||
|
|
||||||
|
SSL/TLS Context
|
||||||
|
---------------
|
||||||
|
|
||||||
|
.. autoclass:: SSLContext
|
||||||
|
:members:
|
||||||
|
|
||||||
|
SSL/TLS Socket
|
||||||
|
--------------
|
||||||
|
|
||||||
|
.. autoclass:: SSLSocket
|
||||||
|
:members:
|
300
wrapper/python/wolfssl/docs/conf.py
Normal file
300
wrapper/python/wolfssl/docs/conf.py
Normal file
@@ -0,0 +1,300 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# wolfcrypt documentation build configuration file, created by
|
||||||
|
# sphinx-quickstart on Fri Apr 29 16:47:53 2016.
|
||||||
|
#
|
||||||
|
# This file is execfile()d with the current directory set to its
|
||||||
|
# containing dir.
|
||||||
|
#
|
||||||
|
# Note that not all possible configuration values are present in this
|
||||||
|
# autogenerated file.
|
||||||
|
#
|
||||||
|
# All configuration values have a default; values that are commented out
|
||||||
|
# serve to show the default.
|
||||||
|
|
||||||
|
# pylint: disable=invalid-name, redefined-builtin, exec-used
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sphinx_rtd_theme
|
||||||
|
|
||||||
|
# If extensions (or modules to document with autodoc) are in another directory,
|
||||||
|
# add these directories to sys.path here. If the directory is relative to the
|
||||||
|
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||||
|
#sys.path.insert(0, os.path.abspath('.'))
|
||||||
|
|
||||||
|
# -- General configuration ------------------------------------------------
|
||||||
|
|
||||||
|
# If your documentation needs a minimal Sphinx version, state it here.
|
||||||
|
#needs_sphinx = '1.0'
|
||||||
|
|
||||||
|
# Add any Sphinx extension module names here, as strings. They can be
|
||||||
|
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||||
|
# ones.
|
||||||
|
extensions = [
|
||||||
|
'sphinx.ext.autodoc',
|
||||||
|
'sphinx.ext.doctest',
|
||||||
|
'sphinx.ext.coverage',
|
||||||
|
'sphinx.ext.viewcode',
|
||||||
|
'sphinx.ext.githubpages',
|
||||||
|
]
|
||||||
|
|
||||||
|
# Add any paths that contain templates here, relative to this directory.
|
||||||
|
templates_path = ['_templates']
|
||||||
|
|
||||||
|
# The suffix(es) of source filenames.
|
||||||
|
# You can specify multiple suffix as a list of string:
|
||||||
|
# source_suffix = ['.rst', '.md']
|
||||||
|
source_suffix = '.rst'
|
||||||
|
|
||||||
|
# The encoding of source files.
|
||||||
|
#source_encoding = 'utf-8-sig'
|
||||||
|
|
||||||
|
# The master toctree document.
|
||||||
|
master_doc = 'index'
|
||||||
|
|
||||||
|
# General information about the project.
|
||||||
|
project = u'wolfssl Python'
|
||||||
|
copyright = u'2017, wolfSSL Inc. All rights reserved'
|
||||||
|
author = u'wolfSSL'
|
||||||
|
|
||||||
|
# The version info for the project you're documenting, acts as replacement for
|
||||||
|
# |version| and |release|, also used in various other places throughout the
|
||||||
|
# built documents.
|
||||||
|
#
|
||||||
|
|
||||||
|
base_dir = os.path.join(os.path.dirname(__file__), os.pardir, "src")
|
||||||
|
about = {}
|
||||||
|
with open(os.path.join(base_dir, "wolfssl", "__about__.py")) as f:
|
||||||
|
exec(f.read(), about)
|
||||||
|
|
||||||
|
version = release = about["__version__"]
|
||||||
|
|
||||||
|
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||||
|
# for a list of supported languages.
|
||||||
|
#
|
||||||
|
# This is also used if you do content translation via gettext catalogs.
|
||||||
|
# Usually you set "language" from the command line for these cases.
|
||||||
|
language = None
|
||||||
|
|
||||||
|
# There are two options for replacing |today|: either, you set today to some
|
||||||
|
# non-false value, then it is used:
|
||||||
|
#today = ''
|
||||||
|
# Else, today_fmt is used as the format for a strftime call.
|
||||||
|
#today_fmt = '%B %d, %Y'
|
||||||
|
|
||||||
|
# List of patterns, relative to source directory, that match files and
|
||||||
|
# directories to ignore when looking for source files.
|
||||||
|
# This patterns also effect to html_static_path and html_extra_path
|
||||||
|
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
||||||
|
|
||||||
|
# The reST default role (used for this markup: `text`) to use for all
|
||||||
|
# documents.
|
||||||
|
#default_role = None
|
||||||
|
|
||||||
|
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||||
|
#add_function_parentheses = True
|
||||||
|
|
||||||
|
# If true, the current module name will be prepended to all description
|
||||||
|
# unit titles (such as .. function::).
|
||||||
|
#add_module_names = True
|
||||||
|
|
||||||
|
# If true, sectionauthor and moduleauthor directives will be shown in the
|
||||||
|
# output. They are ignored by default.
|
||||||
|
#show_authors = False
|
||||||
|
|
||||||
|
# The name of the Pygments (syntax highlighting) style to use.
|
||||||
|
pygments_style = 'sphinx'
|
||||||
|
|
||||||
|
# A list of ignored prefixes for module index sorting.
|
||||||
|
#modindex_common_prefix = []
|
||||||
|
|
||||||
|
# If true, keep warnings as "system message" paragraphs in the built documents.
|
||||||
|
#keep_warnings = False
|
||||||
|
|
||||||
|
# If true, `todo` and `todoList` produce output, else they produce nothing.
|
||||||
|
todo_include_todos = False
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options for HTML output ----------------------------------------------
|
||||||
|
|
||||||
|
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||||
|
# a list of builtin themes.
|
||||||
|
html_theme = 'sphinx_rtd_theme'
|
||||||
|
|
||||||
|
# Theme options are theme-specific and customize the look and feel of a theme
|
||||||
|
# further. For a list of options available for each theme, see the
|
||||||
|
# documentation.
|
||||||
|
#html_theme_options = {}
|
||||||
|
|
||||||
|
# Add any paths that contain custom themes here, relative to this directory.
|
||||||
|
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
|
||||||
|
|
||||||
|
# The name for this set of Sphinx documents.
|
||||||
|
# "<project> v<release> documentation" by default.
|
||||||
|
#html_title = u'%s v%s' % (project, release)
|
||||||
|
|
||||||
|
# A shorter title for the navigation bar. Default is the same as html_title.
|
||||||
|
#html_short_title = None
|
||||||
|
|
||||||
|
# The name of an image file (relative to this directory) to place at the top
|
||||||
|
# of the sidebar.
|
||||||
|
#html_logo = None
|
||||||
|
|
||||||
|
# The name of an image file (relative to this directory) to use as a favicon of
|
||||||
|
# the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||||
|
# pixels large.
|
||||||
|
#html_favicon = None
|
||||||
|
|
||||||
|
# Add any paths that contain custom static files (such as style sheets) here,
|
||||||
|
# relative to this directory. They are copied after the builtin static files,
|
||||||
|
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||||
|
html_static_path = ['_static']
|
||||||
|
|
||||||
|
# Add any extra paths that contain custom files (such as robots.txt or
|
||||||
|
# .htaccess) here, relative to this directory. These files are copied
|
||||||
|
# directly to the root of the documentation.
|
||||||
|
#html_extra_path = []
|
||||||
|
|
||||||
|
# If not None, a 'Last updated on:' timestamp is inserted at every page
|
||||||
|
# bottom, using the given strftime format.
|
||||||
|
# The empty string is equivalent to '%b %d, %Y'.
|
||||||
|
#html_last_updated_fmt = None
|
||||||
|
|
||||||
|
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||||
|
# typographically correct entities.
|
||||||
|
#html_use_smartypants = True
|
||||||
|
|
||||||
|
# Custom sidebar templates, maps document names to template names.
|
||||||
|
#html_sidebars = {}
|
||||||
|
|
||||||
|
# Additional templates that should be rendered to pages, maps page names to
|
||||||
|
# template names.
|
||||||
|
#html_additional_pages = {}
|
||||||
|
|
||||||
|
# If false, no module index is generated.
|
||||||
|
#html_domain_indices = True
|
||||||
|
|
||||||
|
# If false, no index is generated.
|
||||||
|
#html_use_index = True
|
||||||
|
|
||||||
|
# If true, the index is split into individual pages for each letter.
|
||||||
|
#html_split_index = False
|
||||||
|
|
||||||
|
# If true, links to the reST sources are added to the pages.
|
||||||
|
#html_show_sourcelink = True
|
||||||
|
|
||||||
|
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
|
||||||
|
#html_show_sphinx = True
|
||||||
|
|
||||||
|
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
|
||||||
|
#html_show_copyright = True
|
||||||
|
|
||||||
|
# If true, an OpenSearch description file will be output, and all pages will
|
||||||
|
# contain a <link> tag referring to it. The value of this option must be the
|
||||||
|
# base URL from which the finished HTML is served.
|
||||||
|
#html_use_opensearch = ''
|
||||||
|
|
||||||
|
# This is the file name suffix for HTML files (e.g. ".xhtml").
|
||||||
|
#html_file_suffix = None
|
||||||
|
|
||||||
|
# Language to be used for generating the HTML full-text search index.
|
||||||
|
# Sphinx supports the following languages:
|
||||||
|
# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja'
|
||||||
|
# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr', 'zh'
|
||||||
|
#html_search_language = 'en'
|
||||||
|
|
||||||
|
# A dictionary with options for the search language support, empty by default.
|
||||||
|
# 'ja' uses this config value.
|
||||||
|
# 'zh' user can custom change `jieba` dictionary path.
|
||||||
|
#html_search_options = {'type': 'default'}
|
||||||
|
|
||||||
|
# The name of a javascript file (relative to the configuration directory) that
|
||||||
|
# implements a search results scorer. If empty, the default will be used.
|
||||||
|
#html_search_scorer = 'scorer.js'
|
||||||
|
|
||||||
|
# Output file base name for HTML help builder.
|
||||||
|
htmlhelp_basename = 'wolfssl-pydoc'
|
||||||
|
|
||||||
|
# -- Options for LaTeX output ---------------------------------------------
|
||||||
|
|
||||||
|
latex_elements = {
|
||||||
|
# The paper size ('letterpaper' or 'a4paper').
|
||||||
|
#'papersize': 'letterpaper',
|
||||||
|
|
||||||
|
# The font size ('10pt', '11pt' or '12pt').
|
||||||
|
#'pointsize': '10pt',
|
||||||
|
|
||||||
|
# Additional stuff for the LaTeX preamble.
|
||||||
|
#'preamble': '',
|
||||||
|
|
||||||
|
# Latex figure (float) alignment
|
||||||
|
#'figure_align': 'htbp',
|
||||||
|
}
|
||||||
|
|
||||||
|
# Grouping the document tree into LaTeX files. List of tuples
|
||||||
|
# (source start file, target name, title,
|
||||||
|
# author, documentclass [howto, manual, or own class]).
|
||||||
|
latex_documents = [
|
||||||
|
(master_doc, 'wolfssl.tex', u'wolfssl Python Documentation',
|
||||||
|
u'wolfSSL', 'manual'),
|
||||||
|
]
|
||||||
|
|
||||||
|
# The name of an image file (relative to this directory) to place at the top of
|
||||||
|
# the title page.
|
||||||
|
#latex_logo = None
|
||||||
|
|
||||||
|
# For "manual" documents, if this is true, then toplevel headings are parts,
|
||||||
|
# not chapters.
|
||||||
|
#latex_use_parts = False
|
||||||
|
|
||||||
|
# If true, show page references after internal links.
|
||||||
|
#latex_show_pagerefs = False
|
||||||
|
|
||||||
|
# If true, show URL addresses after external links.
|
||||||
|
#latex_show_urls = False
|
||||||
|
|
||||||
|
# Documents to append as an appendix to all manuals.
|
||||||
|
#latex_appendices = []
|
||||||
|
|
||||||
|
# If false, no module index is generated.
|
||||||
|
#latex_domain_indices = True
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options for manual page output ---------------------------------------
|
||||||
|
|
||||||
|
# One entry per manual page. List of tuples
|
||||||
|
# (source start file, name, description, authors, manual section).
|
||||||
|
man_pages = [
|
||||||
|
(master_doc, 'wolfssl', u'wolfssl Python Documentation',
|
||||||
|
[author], 1)
|
||||||
|
]
|
||||||
|
|
||||||
|
# If true, show URL addresses after external links.
|
||||||
|
#man_show_urls = False
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options for Texinfo output -------------------------------------------
|
||||||
|
|
||||||
|
# Grouping the document tree into Texinfo files. List of tuples
|
||||||
|
# (source start file, target name, title, author,
|
||||||
|
# dir menu entry, description, category)
|
||||||
|
texinfo_documents = [
|
||||||
|
(master_doc, 'wolfssl', u'wolfssl Python Documentation',
|
||||||
|
author, 'wolfssl', 'One line description of project.',
|
||||||
|
'Miscellaneous'),
|
||||||
|
]
|
||||||
|
|
||||||
|
# Documents to append as an appendix to all manuals.
|
||||||
|
#texinfo_appendices = []
|
||||||
|
|
||||||
|
# If false, no module index is generated.
|
||||||
|
#texinfo_domain_indices = True
|
||||||
|
|
||||||
|
# How to display URL addresses: 'footnote', 'no', or 'inline'.
|
||||||
|
#texinfo_show_urls = 'footnote'
|
||||||
|
|
||||||
|
# If true, do not generate a @detailmenu in the "Top" node's menu.
|
||||||
|
#texinfo_no_detailmenu = False
|
||||||
|
|
||||||
|
# Preserves the order of the members, doesn't sorts them alphabetically.
|
||||||
|
autodoc_member_order = 'bysource'
|
95
wrapper/python/wolfssl/docs/examples.rst
Normal file
95
wrapper/python/wolfssl/docs/examples.rst
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
Client and Server Examples
|
||||||
|
==========================
|
||||||
|
|
||||||
|
SSL/TLS Client Example
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
import socket
|
||||||
|
import wolfssl
|
||||||
|
|
||||||
|
CA_DATA = \
|
||||||
|
"""
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs
|
||||||
|
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
|
||||||
|
d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
|
||||||
|
ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL
|
||||||
|
MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
|
||||||
|
LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
|
||||||
|
RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm
|
||||||
|
+9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW
|
||||||
|
PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM
|
||||||
|
xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB
|
||||||
|
Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3
|
||||||
|
hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg
|
||||||
|
EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF
|
||||||
|
MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA
|
||||||
|
FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec
|
||||||
|
nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z
|
||||||
|
eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF
|
||||||
|
hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2
|
||||||
|
Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
|
||||||
|
vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep
|
||||||
|
+OkuE6N36B9K
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
"""
|
||||||
|
|
||||||
|
bind_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
|
||||||
|
|
||||||
|
context = wolfssl.SSLContext(wolfssl.PROTOCOL_TLSv1_2)
|
||||||
|
|
||||||
|
context.verify_mode = wolfssl.CERT_REQUIRED
|
||||||
|
context.load_verify_locations(cadata=CA_DATA)
|
||||||
|
|
||||||
|
secure_socket = context.wrap_socket(bind_socket)
|
||||||
|
|
||||||
|
secure_socket.connect(("www.python.org", 443))
|
||||||
|
|
||||||
|
secure_socket.write(b"GET / HTTP/1.1\n\n")
|
||||||
|
|
||||||
|
print(secure_socket.read())
|
||||||
|
|
||||||
|
secure_socket.close()
|
||||||
|
|
||||||
|
|
||||||
|
SSL/TLS Server Example
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
import socket
|
||||||
|
import wolfssl
|
||||||
|
|
||||||
|
bind_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
|
||||||
|
|
||||||
|
bind_socket.bind(("", 4433))
|
||||||
|
bind_socket.listen(5)
|
||||||
|
|
||||||
|
context = wolfssl.SSLContext(wolfssl.PROTOCOL_TLSv1_2, server_side=True)
|
||||||
|
|
||||||
|
context.load_cert_chain("certs/server-cert.pem", "certs/server-key.pem")
|
||||||
|
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
secure_socket = None
|
||||||
|
|
||||||
|
new_socket, from_addr = bind_socket.accept()
|
||||||
|
|
||||||
|
secure_socket = context.wrap_socket(new_socket)
|
||||||
|
|
||||||
|
print("Connection received from", from_addr)
|
||||||
|
|
||||||
|
print("\n", secure_socket.read(), "\n")
|
||||||
|
secure_socket.write(b"I hear you fa shizzle!")
|
||||||
|
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print()
|
||||||
|
break
|
||||||
|
|
||||||
|
finally:
|
||||||
|
if secure_socket:
|
||||||
|
secure_socket.close()
|
||||||
|
|
||||||
|
bind_socket.close()
|
8
wrapper/python/wolfssl/docs/index.rst
Normal file
8
wrapper/python/wolfssl/docs/index.rst
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
installation
|
||||||
|
usage
|
||||||
|
api
|
||||||
|
examples
|
||||||
|
licensing
|
1
wrapper/python/wolfssl/docs/installation.rst
Normal file
1
wrapper/python/wolfssl/docs/installation.rst
Normal file
@@ -0,0 +1 @@
|
|||||||
|
.. include:: ../README.rst
|
1
wrapper/python/wolfssl/docs/licensing.rst
Normal file
1
wrapper/python/wolfssl/docs/licensing.rst
Normal file
@@ -0,0 +1 @@
|
|||||||
|
.. include:: ../LICENSING.rst
|
2
wrapper/python/wolfssl/docs/requirements.txt
Normal file
2
wrapper/python/wolfssl/docs/requirements.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
Sphinx
|
||||||
|
sphinx_rtd_theme
|
87
wrapper/python/wolfssl/docs/usage.rst
Normal file
87
wrapper/python/wolfssl/docs/usage.rst
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
Basic Usage
|
||||||
|
===========
|
||||||
|
|
||||||
|
The SSL/TLS protocol works securing an underlying TCP connection, this module
|
||||||
|
adds the secure layer around the Python standard library
|
||||||
|
`socket <https://docs.python.org/3.6/library/socket.html>`_ module.
|
||||||
|
|
||||||
|
There are three different paths to secure a socket in this module:
|
||||||
|
|
||||||
|
* Using the top level function wolfssl.wrap_socket();
|
||||||
|
* Using the method wrap_socket() from a SSLContext instance;
|
||||||
|
* Creating an SSLSocket object from the scratch.
|
||||||
|
|
||||||
|
Note 1:
|
||||||
|
It is possible to use the same SSLContext for multiple SSLSockets to save
|
||||||
|
time and resources.
|
||||||
|
|
||||||
|
Note 2:
|
||||||
|
Each path provides its own options for fine-tuning the securint parameters.
|
||||||
|
Check them out in the API documentation.
|
||||||
|
|
||||||
|
|
||||||
|
Using the top level function wolfssl.wrap_socket()
|
||||||
|
--------------------------------------------------
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
>>> import socket
|
||||||
|
>>> import wolfssl
|
||||||
|
>>>
|
||||||
|
>>> sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
|
||||||
|
>>>
|
||||||
|
>>> secure_socket = wolfssl.wrap_socket(sock)
|
||||||
|
>>>
|
||||||
|
>>> secure_socket.connect(("www.python.org", 443))
|
||||||
|
>>>
|
||||||
|
>>> secure_socket.write(b"GET / HTTP/1.1\n\n")
|
||||||
|
>>>
|
||||||
|
>>> print(secure_socket.read())
|
||||||
|
b'HTTP/1.1 500 Domain Not Found\r\nServer: Varnish\r\nRetry-After: 0\r\ncontent-type: text/html\r\nCache-Control: private, no-cache\r\nconnection: keep-alive\r\nContent-Length: 179\r\nAccept-Ranges: bytes\r\nDate: Sun, 05 Feb 2017 21:26:48 GMT\r\nVia: 1.1 varnish\r\nConnection: keep-alive\r\n\r\n\n<html>\n<head>\n<title>Fastly error: unknown domain </title>\n</head>\n<body>\nFastly error: unknown domain: . Please check that this domain has been added to a service.</body></html>'
|
||||||
|
>>>
|
||||||
|
>>> secure_socket.close()
|
||||||
|
|
||||||
|
|
||||||
|
Using the method wrap_socket() from a SSLContext instance
|
||||||
|
---------------------------------------------------------
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
>>> import socket
|
||||||
|
>>> import wolfssl
|
||||||
|
>>>
|
||||||
|
>>> sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
|
||||||
|
>>>
|
||||||
|
>>> context = wolfssl.SSLContext(wolfssl.PROTOCOL_TLSv1_2)
|
||||||
|
>>>
|
||||||
|
>>> secure_socket = context.wrap_socket(sock)
|
||||||
|
>>>
|
||||||
|
>>> secure_socket.connect(("www.python.org", 443))
|
||||||
|
>>>
|
||||||
|
>>> secure_socket.write(b"GET / HTTP/1.1\n\n")
|
||||||
|
>>>
|
||||||
|
>>> print(secure_socket.read())
|
||||||
|
b'HTTP/1.1 500 Domain Not Found\r\nServer: Varnish\r\nRetry-After: 0\r\ncontent-type: text/html\r\nCache-Control: private, no-cache\r\nconnection: keep-alive\r\nContent-Length: 179\r\nAccept-Ranges: bytes\r\nDate: Sun, 05 Feb 2017 21:26:48 GMT\r\nVia: 1.1 varnish\r\nConnection: keep-alive\r\n\r\n\n<html>\n<head>\n<title>Fastly error: unknown domain </title>\n</head>\n<body>\nFastly error: unknown domain: . Please check that this domain has been added to a service.</body></html>'
|
||||||
|
>>>
|
||||||
|
>>> secure_socket.close()
|
||||||
|
|
||||||
|
Creating an SSLSocket object from the scratch
|
||||||
|
---------------------------------------------
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
>>> import socket
|
||||||
|
>>> import wolfssl
|
||||||
|
>>>
|
||||||
|
>>> sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
|
||||||
|
>>>
|
||||||
|
>>> secure_socket = wolfssl.SSLSocket(sock)
|
||||||
|
>>>
|
||||||
|
>>> secure_socket.connect(("www.python.org", 443))
|
||||||
|
>>>
|
||||||
|
>>> secure_socket.write(b"GET / HTTP/1.1\n\n")
|
||||||
|
>>>
|
||||||
|
>>> print(secure_socket.read())
|
||||||
|
b'HTTP/1.1 500 Domain Not Found\r\nServer: Varnish\r\nRetry-After: 0\r\ncontent-type: text/html\r\nCache-Control: private, no-cache\r\nconnection: keep-alive\r\nContent-Length: 179\r\nAccept-Ranges: bytes\r\nDate: Sun, 05 Feb 2017 21:26:48 GMT\r\nVia: 1.1 varnish\r\nConnection: keep-alive\r\n\r\n\n<html>\n<head>\n<title>Fastly error: unknown domain </title>\n</head>\n<body>\nFastly error: unknown domain: . Please check that this domain has been added to a service.</body></html>'
|
||||||
|
>>>
|
||||||
|
>>> secure_socket.close()
|
140
wrapper/python/wolfssl/examples/client.py
Executable file
140
wrapper/python/wolfssl/examples/client.py
Executable file
@@ -0,0 +1,140 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# client.py
|
||||||
|
#
|
||||||
|
# Copyright (C) 2006-2017 wolfSSL Inc.
|
||||||
|
#
|
||||||
|
# This file is part of wolfSSL. (formerly known as CyaSSL)
|
||||||
|
#
|
||||||
|
# wolfSSL is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# wolfSSL is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
|
||||||
|
# pylint: disable=missing-docstring, invalid-name, import-error
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import socket
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
try:
|
||||||
|
import wolfssl
|
||||||
|
except ImportError:
|
||||||
|
print("You must run 'python setup.py install' to use the examples")
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
|
def build_arg_parser():
|
||||||
|
parser = argparse.ArgumentParser(add_help=False)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"-?", "--help", action="help",
|
||||||
|
help="show this help message and exit"
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"-h", metavar="host", default="127.0.0.1",
|
||||||
|
help="Host to connect to, default 127.0.0.1"
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"-p", metavar="port", type=int, default=11111,
|
||||||
|
help="Port to connect on, not 0, default 11111"
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"-v", metavar="version", type=int, choices=[0, 1, 2, 3], default=3,
|
||||||
|
help="SSL version [0-3], SSLv3(0) - TLS1.2(3)), default 3"
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"-l", metavar="ciphers", type=str, default="",
|
||||||
|
help="Cipher suite list (: delimited)"
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"-c", metavar="certificate", default="./certs/client-cert.pem",
|
||||||
|
help="Certificate file, default ./certs/client-cert.pem"
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"-k", metavar="key", default="./certs/client-key.pem",
|
||||||
|
help="Key file, default ./certs/client-key.pem"
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"-A", metavar="ca_file", default="./certs/ca-cert.pem",
|
||||||
|
help="Certificate Authority file, default ./certs/ca-cert.pem"
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"-d", action="store_true",
|
||||||
|
help="Disable client cert check"
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"-g", action="store_true",
|
||||||
|
help="Send server HTTP GET"
|
||||||
|
)
|
||||||
|
|
||||||
|
return parser
|
||||||
|
|
||||||
|
|
||||||
|
def get_method(index):
|
||||||
|
return (
|
||||||
|
wolfssl.PROTOCOL_SSLv3,
|
||||||
|
wolfssl.PROTOCOL_TLSv1,
|
||||||
|
wolfssl.PROTOCOL_TLSv1_1,
|
||||||
|
wolfssl.PROTOCOL_TLSv1_2
|
||||||
|
)[index]
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
args = build_arg_parser().parse_args()
|
||||||
|
|
||||||
|
bind_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
|
||||||
|
|
||||||
|
context = wolfssl.SSLContext(get_method(args.v))
|
||||||
|
|
||||||
|
context.load_cert_chain(args.c, args.k)
|
||||||
|
|
||||||
|
if args.d:
|
||||||
|
context.verify_mode = wolfssl.CERT_NONE
|
||||||
|
else:
|
||||||
|
context.verify_mode = wolfssl.CERT_REQUIRED
|
||||||
|
context.load_verify_locations(args.A)
|
||||||
|
|
||||||
|
if args.l:
|
||||||
|
context.set_ciphers(args.l)
|
||||||
|
|
||||||
|
try:
|
||||||
|
secure_socket = context.wrap_socket(bind_socket)
|
||||||
|
|
||||||
|
secure_socket.connect((args.h, args.p))
|
||||||
|
|
||||||
|
if args.g:
|
||||||
|
secure_socket.write(b"GET / HTTP/1.1\n\n")
|
||||||
|
else:
|
||||||
|
secure_socket.write(b"hello wolfssl")
|
||||||
|
|
||||||
|
print("\n", secure_socket.read(), "\n")
|
||||||
|
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print()
|
||||||
|
|
||||||
|
finally:
|
||||||
|
secure_socket.close()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
152
wrapper/python/wolfssl/examples/server.py
Executable file
152
wrapper/python/wolfssl/examples/server.py
Executable file
@@ -0,0 +1,152 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# server.py
|
||||||
|
#
|
||||||
|
# Copyright (C) 2006-2017 wolfSSL Inc.
|
||||||
|
#
|
||||||
|
# This file is part of wolfSSL. (formerly known as CyaSSL)
|
||||||
|
#
|
||||||
|
# wolfSSL is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# wolfSSL is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
|
||||||
|
# pylint: disable=missing-docstring, invalid-name, import-error
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import socket
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
try:
|
||||||
|
import wolfssl
|
||||||
|
except ImportError:
|
||||||
|
print("You must run 'python setup.py install' to use the examples")
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
|
def build_arg_parser():
|
||||||
|
parser = argparse.ArgumentParser(add_help=False)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"-?", "--help", action="help",
|
||||||
|
help="show this help message and exit"
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"-p", metavar="port", type=int, default=11111,
|
||||||
|
help="Port to listen on, not 0, default 11111"
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"-v", metavar="version", type=int, choices=[0, 1, 2, 3], default=3,
|
||||||
|
help="SSL version [0-3], SSLv3(0) - TLS1.2(3)), default 3"
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"-l", metavar="ciphers", type=str, default="",
|
||||||
|
help="Cipher suite list (: delimited)"
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"-c", metavar="certificate", default="./certs/server-cert.pem",
|
||||||
|
help="Certificate file, default ./certs/server-cert.pem"
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"-k", metavar="key", default="./certs/server-key.pem",
|
||||||
|
help="Key file, default ./certs/server-key.pem"
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"-A", metavar="ca_file", default="./certs/client-cert.pem",
|
||||||
|
help="Certificate Authority file, default ./certs/client-cert.pem"
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"-d", action="store_true",
|
||||||
|
help="Disable client cert check"
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"-b", action="store_true",
|
||||||
|
help="Bind to any interface instead of localhost only"
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"-i", action="store_true",
|
||||||
|
help="Loop indefinitely (allow repeated connections)"
|
||||||
|
)
|
||||||
|
|
||||||
|
return parser
|
||||||
|
|
||||||
|
|
||||||
|
def get_method(index):
|
||||||
|
return (
|
||||||
|
wolfssl.PROTOCOL_SSLv3,
|
||||||
|
wolfssl.PROTOCOL_TLSv1,
|
||||||
|
wolfssl.PROTOCOL_TLSv1_1,
|
||||||
|
wolfssl.PROTOCOL_TLSv1_2
|
||||||
|
)[index]
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
args = build_arg_parser().parse_args()
|
||||||
|
|
||||||
|
bind_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
|
||||||
|
bind_socket.bind(("" if args.b else "localhost", args.p))
|
||||||
|
bind_socket.listen(5)
|
||||||
|
|
||||||
|
print("Server listening on port", bind_socket.getsockname()[1])
|
||||||
|
|
||||||
|
context = wolfssl.SSLContext(get_method(args.v), server_side=True)
|
||||||
|
|
||||||
|
context.load_cert_chain(args.c, args.k)
|
||||||
|
|
||||||
|
if args.d:
|
||||||
|
context.verify_mode = wolfssl.CERT_NONE
|
||||||
|
else:
|
||||||
|
context.verify_mode = wolfssl.CERT_REQUIRED
|
||||||
|
context.load_verify_locations(args.A)
|
||||||
|
|
||||||
|
if args.l:
|
||||||
|
context.set_ciphers(args.l)
|
||||||
|
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
secure_socket = None
|
||||||
|
|
||||||
|
new_socket, from_addr = bind_socket.accept()
|
||||||
|
|
||||||
|
secure_socket = context.wrap_socket(new_socket)
|
||||||
|
|
||||||
|
print("Connection received from", from_addr)
|
||||||
|
|
||||||
|
print("\n", secure_socket.read(), "\n")
|
||||||
|
secure_socket.write(b"I hear you fa shizzle!")
|
||||||
|
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print()
|
||||||
|
break
|
||||||
|
|
||||||
|
finally:
|
||||||
|
if secure_socket:
|
||||||
|
secure_socket.close()
|
||||||
|
|
||||||
|
if not args.i:
|
||||||
|
break
|
||||||
|
|
||||||
|
bind_socket.close()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
38
wrapper/python/wolfssl/include.am
Normal file
38
wrapper/python/wolfssl/include.am
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
# vim:ft=automake
|
||||||
|
# included from Top Level Makefile.am
|
||||||
|
# All paths should be given relative to the root
|
||||||
|
|
||||||
|
EXTRA_DIST+= wrapper/python/wolfssl/.gitignore
|
||||||
|
EXTRA_DIST+= wrapper/python/wolfssl/docs/api.rst
|
||||||
|
EXTRA_DIST+= wrapper/python/wolfssl/docs/conf.py
|
||||||
|
EXTRA_DIST+= wrapper/python/wolfssl/docs/examples.rst
|
||||||
|
EXTRA_DIST+= wrapper/python/wolfssl/docs/index.rst
|
||||||
|
EXTRA_DIST+= wrapper/python/wolfssl/docs/installation.rst
|
||||||
|
EXTRA_DIST+= wrapper/python/wolfssl/docs/Makefile
|
||||||
|
EXTRA_DIST+= wrapper/python/wolfssl/docs/licensing.rst
|
||||||
|
EXTRA_DIST+= wrapper/python/wolfssl/docs/requirements.txt
|
||||||
|
EXTRA_DIST+= wrapper/python/wolfssl/docs/usage.rst
|
||||||
|
EXTRA_DIST+= wrapper/python/wolfssl/examples/client.py
|
||||||
|
EXTRA_DIST+= wrapper/python/wolfssl/examples/server.py
|
||||||
|
EXTRA_DIST+= wrapper/python/wolfssl/test/conftest.py
|
||||||
|
EXTRA_DIST+= wrapper/python/wolfssl/test/test_client.py
|
||||||
|
EXTRA_DIST+= wrapper/python/wolfssl/test/test_context.py
|
||||||
|
EXTRA_DIST+= wrapper/python/wolfssl/test/test_methods.py
|
||||||
|
EXTRA_DIST+= wrapper/python/wolfssl/src/wolfssl/__about__.py
|
||||||
|
EXTRA_DIST+= wrapper/python/wolfssl/src/wolfssl/__init__.py
|
||||||
|
EXTRA_DIST+= wrapper/python/wolfssl/src/wolfssl/build_ffi.py
|
||||||
|
EXTRA_DIST+= wrapper/python/wolfssl/src/wolfssl/_memory.py
|
||||||
|
EXTRA_DIST+= wrapper/python/wolfssl/src/wolfssl/_methods.py
|
||||||
|
EXTRA_DIST+= wrapper/python/wolfssl/src/wolfssl/exceptions.py
|
||||||
|
EXTRA_DIST+= wrapper/python/wolfssl/src/wolfssl/utils.py
|
||||||
|
EXTRA_DIST+= wrapper/python/wolfssl/LICENSING.rst
|
||||||
|
EXTRA_DIST+= wrapper/python/wolfssl/Makefile
|
||||||
|
EXTRA_DIST+= wrapper/python/wolfssl/MANIFEST.in
|
||||||
|
EXTRA_DIST+= wrapper/python/wolfssl/README.rst
|
||||||
|
EXTRA_DIST+= wrapper/python/wolfssl/requirements-testing.txt
|
||||||
|
EXTRA_DIST+= wrapper/python/wolfssl/setup.py
|
||||||
|
EXTRA_DIST+= wrapper/python/wolfssl/tox.ini
|
||||||
|
EXTRA_DIST+= wrapper/python/wolfssl/Vagrantfile
|
||||||
|
EXTRA_DIST+= wrapper/python/wolfssl/.centos-provisioner.sh
|
||||||
|
EXTRA_DIST+= wrapper/python/wolfssl/.ubuntu-provisioner.sh
|
||||||
|
|
3
wrapper/python/wolfssl/requirements-testing.txt
Normal file
3
wrapper/python/wolfssl/requirements-testing.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
pytest
|
||||||
|
cffi
|
||||||
|
tox
|
87
wrapper/python/wolfssl/setup.py
Executable file
87
wrapper/python/wolfssl/setup.py
Executable file
@@ -0,0 +1,87 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# setup.py
|
||||||
|
#
|
||||||
|
# Copyright (C) 2006-2017 wolfSSL Inc.
|
||||||
|
#
|
||||||
|
# This file is part of wolfSSL. (formerly known as CyaSSL)
|
||||||
|
#
|
||||||
|
# wolfSSL is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# wolfSSL is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
|
||||||
|
# Python 2.7 Standard Library
|
||||||
|
|
||||||
|
# pylint: disable=import-error, wrong-import-position
|
||||||
|
|
||||||
|
from __future__ import absolute_import
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import shutil
|
||||||
|
from setuptools import setup, find_packages
|
||||||
|
|
||||||
|
sys.path.insert(0, 'src')
|
||||||
|
from wolfssl.__about__ import METADATA
|
||||||
|
|
||||||
|
os.chdir(os.path.dirname(sys.argv[0]) or ".")
|
||||||
|
|
||||||
|
LONG_DESCRIPTION = open("README.rst", "rt").read().replace(
|
||||||
|
".. include:: LICENSING.rst\n",
|
||||||
|
open("LICENSING.rst", "rt").read()
|
||||||
|
)
|
||||||
|
|
||||||
|
INFO = dict(
|
||||||
|
metadata={k[2:-2]: METADATA[k] for k in METADATA},
|
||||||
|
contents={
|
||||||
|
"long_description" : LONG_DESCRIPTION,
|
||||||
|
"package_data" : {"": ["*.txt"]},
|
||||||
|
"packages" : find_packages("src"),
|
||||||
|
"package_dir" : {"": "src"},
|
||||||
|
"cffi_modules" : ["./src/wolfssl/build_ffi.py:ffi"],
|
||||||
|
},
|
||||||
|
requirements={
|
||||||
|
"setup_requires" : ["cffi>=1.6.0"],
|
||||||
|
"install_requires" : ["cffi>=1.6.0"],
|
||||||
|
},
|
||||||
|
scripts={},
|
||||||
|
plugins={},
|
||||||
|
tests={},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def update_certs():
|
||||||
|
c_certs_dir = "../../../certs"
|
||||||
|
py_certs_dir = "certs"
|
||||||
|
certs = [
|
||||||
|
"ca-cert.pem",
|
||||||
|
"client-cert.pem",
|
||||||
|
"client-key.pem",
|
||||||
|
"server-cert.pem",
|
||||||
|
"server-key.pem",
|
||||||
|
"external/ca-digicert-ev.pem"
|
||||||
|
]
|
||||||
|
|
||||||
|
if os.path.isdir(c_certs_dir):
|
||||||
|
if not os.path.isdir(py_certs_dir):
|
||||||
|
os.makedirs(py_certs_dir)
|
||||||
|
|
||||||
|
for cert in certs:
|
||||||
|
shutil.copy(os.path.join(c_certs_dir, cert), py_certs_dir)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
update_certs()
|
||||||
|
|
||||||
|
KWARGS = {k:v for dct in INFO.values() for (k, v) in dct.items()}
|
||||||
|
setup(**KWARGS)
|
49
wrapper/python/wolfssl/src/wolfssl/__about__.py
Normal file
49
wrapper/python/wolfssl/src/wolfssl/__about__.py
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# __about__.py
|
||||||
|
#
|
||||||
|
# Copyright (C) 2006-2017 wolfSSL Inc.
|
||||||
|
#
|
||||||
|
# This file is part of wolfSSL. (formerly known as CyaSSL)
|
||||||
|
#
|
||||||
|
# wolfSSL is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# wolfSSL is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
|
||||||
|
# pylint: disable=missing-docstring
|
||||||
|
|
||||||
|
METADATA = dict(
|
||||||
|
__name__="wolfssl",
|
||||||
|
__version__="0.1.0",
|
||||||
|
__license__="GPLv2 or Commercial License",
|
||||||
|
__author__="wolfSSL Inc.",
|
||||||
|
__author_email__="info@wolfssl.com",
|
||||||
|
__url__="https://wolfssl.github.io/wolfssl-py",
|
||||||
|
__description__= \
|
||||||
|
u"A Python module that encapsulates wolfSSL's C SSL/TLS library.",
|
||||||
|
__keywords__="security, cryptography, ssl, embedded, embedded ssl",
|
||||||
|
__classifiers__=[
|
||||||
|
u"License :: OSI Approved :: GNU General Public License v2 (GPLv2)",
|
||||||
|
u"License :: Other/Proprietary License",
|
||||||
|
u"Operating System :: OS Independent",
|
||||||
|
u"Programming Language :: Python :: 2.7",
|
||||||
|
u"Programming Language :: Python :: 3.5",
|
||||||
|
u"Topic :: Security",
|
||||||
|
u"Topic :: Security :: Cryptography",
|
||||||
|
u"Topic :: Software Development"
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
globals().update(METADATA)
|
||||||
|
|
||||||
|
__all__ = list(METADATA.keys())
|
677
wrapper/python/wolfssl/src/wolfssl/__init__.py
Normal file
677
wrapper/python/wolfssl/src/wolfssl/__init__.py
Normal file
@@ -0,0 +1,677 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# __init__.py
|
||||||
|
#
|
||||||
|
# Copyright (C) 2006-2017 wolfSSL Inc.
|
||||||
|
#
|
||||||
|
# This file is part of wolfSSL. (formerly known as CyaSSL)
|
||||||
|
#
|
||||||
|
# wolfSSL is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# wolfSSL is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import errno
|
||||||
|
from socket import (
|
||||||
|
socket, AF_INET, SOCK_STREAM, SOL_SOCKET, SO_TYPE, error as socket_error
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
from wolfssl._ffi import ffi as _ffi
|
||||||
|
from wolfssl._ffi import lib as _lib
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
from wolfssl.utils import t2b
|
||||||
|
|
||||||
|
from wolfssl.exceptions import (
|
||||||
|
CertificateError, SSLError, SSLEOFError, SSLSyscallError,
|
||||||
|
SSLWantReadError, SSLWantWriteError, SSLZeroReturnError
|
||||||
|
)
|
||||||
|
|
||||||
|
from wolfssl._methods import (
|
||||||
|
PROTOCOL_SSLv23, PROTOCOL_SSLv3, PROTOCOL_TLSv1,
|
||||||
|
PROTOCOL_TLSv1_1, PROTOCOL_TLSv1_2, PROTOCOL_TLS,
|
||||||
|
WolfSSLMethod as _WolfSSLMethod
|
||||||
|
)
|
||||||
|
|
||||||
|
from wolfssl.__about__ import (
|
||||||
|
__all__, METADATA
|
||||||
|
)
|
||||||
|
|
||||||
|
globals().update(METADATA)
|
||||||
|
|
||||||
|
CERT_NONE = 0
|
||||||
|
CERT_REQUIRED = 1
|
||||||
|
|
||||||
|
_VERIFY_MODE_LIST = [CERT_NONE, CERT_REQUIRED]
|
||||||
|
|
||||||
|
_SSL_SUCCESS = 1
|
||||||
|
_SSL_FILETYPE_PEM = 1
|
||||||
|
_SSL_ERROR_WANT_READ = 2
|
||||||
|
|
||||||
|
_WOLFSSL_ECC_SECP160K1 = 15
|
||||||
|
_WOLFSSL_ECC_SECP160R1 = 16
|
||||||
|
_WOLFSSL_ECC_SECP160R2 = 17
|
||||||
|
_WOLFSSL_ECC_SECP192K1 = 18
|
||||||
|
_WOLFSSL_ECC_SECP192R1 = 19
|
||||||
|
_WOLFSSL_ECC_SECP224K1 = 20
|
||||||
|
_WOLFSSL_ECC_SECP224R1 = 21
|
||||||
|
_WOLFSSL_ECC_SECP256K1 = 22
|
||||||
|
_WOLFSSL_ECC_SECP256R1 = 23
|
||||||
|
_WOLFSSL_ECC_SECP384R1 = 24
|
||||||
|
_WOLFSSL_ECC_SECP521R1 = 25
|
||||||
|
_WOLFSSL_ECC_BRAINPOOLP256R1 = 26
|
||||||
|
_WOLFSSL_ECC_BRAINPOOLP384R1 = 27
|
||||||
|
_WOLFSSL_ECC_BRAINPOOLP512R1 = 28
|
||||||
|
|
||||||
|
_SUPPORTED_CURVES = [
|
||||||
|
_WOLFSSL_ECC_SECP160K1, _WOLFSSL_ECC_SECP160R1, _WOLFSSL_ECC_SECP160R2,
|
||||||
|
_WOLFSSL_ECC_SECP192K1, _WOLFSSL_ECC_SECP192R1, _WOLFSSL_ECC_SECP224K1,
|
||||||
|
_WOLFSSL_ECC_SECP224R1, _WOLFSSL_ECC_SECP256K1, _WOLFSSL_ECC_SECP256R1,
|
||||||
|
_WOLFSSL_ECC_SECP384R1, _WOLFSSL_ECC_SECP521R1,
|
||||||
|
_WOLFSSL_ECC_BRAINPOOLP256R1, _WOLFSSL_ECC_BRAINPOOLP384R1,
|
||||||
|
_WOLFSSL_ECC_BRAINPOOLP512R1
|
||||||
|
]
|
||||||
|
|
||||||
|
_PY3 = sys.version_info[0] == 3
|
||||||
|
|
||||||
|
class SSLContext(object):
|
||||||
|
"""
|
||||||
|
An SSLContext holds various SSL-related configuration options and
|
||||||
|
data, such as certificates and possibly a private key.
|
||||||
|
"""
|
||||||
|
|
||||||
|
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 __del__(self):
|
||||||
|
if getattr(self, 'native_object', _ffi.NULL) != _ffi.NULL:
|
||||||
|
_lib.wolfSSL_CTX_free(self.native_object)
|
||||||
|
|
||||||
|
|
||||||
|
@property
|
||||||
|
def verify_mode(self):
|
||||||
|
"""
|
||||||
|
Whether to try to verify other peers’ certificates and how to behave
|
||||||
|
if verification fails. This attribute must be one of CERT_NONE,
|
||||||
|
CERT_OPTIONAL or CERT_REQUIRED.
|
||||||
|
"""
|
||||||
|
return self._verify_mode
|
||||||
|
|
||||||
|
|
||||||
|
@verify_mode.setter
|
||||||
|
def verify_mode(self, value):
|
||||||
|
if value not in _VERIFY_MODE_LIST:
|
||||||
|
raise ValueError("verify_mode must be one of CERT_NONE, "
|
||||||
|
"CERT_OPTIONAL or CERT_REQUIRED")
|
||||||
|
|
||||||
|
if value != self._verify_mode:
|
||||||
|
self._verify_mode = value
|
||||||
|
_lib.wolfSSL_CTX_set_verify(self.native_object,
|
||||||
|
self._verify_mode,
|
||||||
|
_ffi.NULL)
|
||||||
|
|
||||||
|
|
||||||
|
def wrap_socket(self, sock, server_side=False,
|
||||||
|
do_handshake_on_connect=True,
|
||||||
|
suppress_ragged_eofs=True):
|
||||||
|
"""
|
||||||
|
Wrap an existing Python socket sock and return an SSLSocket object.
|
||||||
|
sock must be a SOCK_STREAM socket; other socket types are unsupported.
|
||||||
|
|
||||||
|
The returned SSL socket is tied to the context, its settings and
|
||||||
|
certificates. The parameters server_side, do_handshake_on_connect and
|
||||||
|
suppress_ragged_eofs have the same meaning as in the top-level
|
||||||
|
wrap_socket() function.
|
||||||
|
"""
|
||||||
|
return SSLSocket(sock=sock, server_side=server_side,
|
||||||
|
do_handshake_on_connect=do_handshake_on_connect,
|
||||||
|
suppress_ragged_eofs=suppress_ragged_eofs,
|
||||||
|
_context=self)
|
||||||
|
|
||||||
|
|
||||||
|
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 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)
|
||||||
|
|
||||||
|
|
||||||
|
class SSLSocket(socket):
|
||||||
|
"""
|
||||||
|
This class implements a subtype of socket.socket that wraps the
|
||||||
|
underlying OS socket in an SSL/TLS connection, providing secure
|
||||||
|
read and write methods over that channel.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, sock=None, keyfile=None, certfile=None,
|
||||||
|
server_side=False, cert_reqs=CERT_NONE,
|
||||||
|
ssl_version=PROTOCOL_TLS, ca_certs=None,
|
||||||
|
do_handshake_on_connect=True, family=AF_INET,
|
||||||
|
sock_type=SOCK_STREAM, proto=0, fileno=None,
|
||||||
|
suppress_ragged_eofs=True, ciphers=None,
|
||||||
|
_context=None):
|
||||||
|
|
||||||
|
# set options
|
||||||
|
self.do_handshake_on_connect = do_handshake_on_connect
|
||||||
|
self.suppress_ragged_eofs = suppress_ragged_eofs
|
||||||
|
self.server_side = server_side
|
||||||
|
|
||||||
|
# set context
|
||||||
|
if _context:
|
||||||
|
self._context = _context
|
||||||
|
else:
|
||||||
|
if server_side and not certfile:
|
||||||
|
raise ValueError("certfile must be specified for server-side "
|
||||||
|
"operations")
|
||||||
|
|
||||||
|
if keyfile and not certfile:
|
||||||
|
raise ValueError("certfile must be specified")
|
||||||
|
|
||||||
|
if certfile and not keyfile:
|
||||||
|
keyfile = certfile
|
||||||
|
|
||||||
|
self._context = SSLContext(ssl_version, server_side)
|
||||||
|
self._context.verify_mode = cert_reqs
|
||||||
|
if ca_certs:
|
||||||
|
self._context.load_verify_locations(ca_certs)
|
||||||
|
if certfile:
|
||||||
|
self._context.load_cert_chain(certfile, keyfile)
|
||||||
|
if ciphers:
|
||||||
|
self._context.set_ciphers(ciphers)
|
||||||
|
|
||||||
|
self.keyfile = keyfile
|
||||||
|
self.certfile = certfile
|
||||||
|
self.cert_reqs = cert_reqs
|
||||||
|
self.ssl_version = ssl_version
|
||||||
|
self.ca_certs = ca_certs
|
||||||
|
self.ciphers = ciphers
|
||||||
|
|
||||||
|
# preparing socket
|
||||||
|
if sock is not None:
|
||||||
|
# Can't use sock.type as other flags (such as SOCK_NONBLOCK) get
|
||||||
|
# mixed in.
|
||||||
|
if sock.getsockopt(SOL_SOCKET, SO_TYPE) != SOCK_STREAM:
|
||||||
|
raise NotImplementedError("only stream sockets are supported")
|
||||||
|
|
||||||
|
if _PY3:
|
||||||
|
socket.__init__(self,
|
||||||
|
family=sock.family,
|
||||||
|
type=sock.type,
|
||||||
|
proto=sock.proto,
|
||||||
|
fileno=sock.fileno())
|
||||||
|
else:
|
||||||
|
socket.__init__(self, _sock=sock._sock)
|
||||||
|
|
||||||
|
self.settimeout(sock.gettimeout())
|
||||||
|
|
||||||
|
if _PY3:
|
||||||
|
sock.detach()
|
||||||
|
|
||||||
|
elif fileno is not None:
|
||||||
|
socket.__init__(self, fileno=fileno)
|
||||||
|
|
||||||
|
else:
|
||||||
|
socket.__init__(self, family=family, type=sock_type,
|
||||||
|
proto=proto)
|
||||||
|
|
||||||
|
# see if we are connected
|
||||||
|
try:
|
||||||
|
self.getpeername()
|
||||||
|
except socket_error as exception:
|
||||||
|
if exception.errno != errno.ENOTCONN:
|
||||||
|
raise
|
||||||
|
connected = False
|
||||||
|
else:
|
||||||
|
connected = True
|
||||||
|
|
||||||
|
self._closed = False
|
||||||
|
self._connected = connected
|
||||||
|
|
||||||
|
# create the SSL object
|
||||||
|
self.native_object = _lib.wolfSSL_new(self.context.native_object)
|
||||||
|
if self.native_object == _ffi.NULL:
|
||||||
|
raise MemoryError("Unnable to allocate ssl object")
|
||||||
|
|
||||||
|
ret = _lib.wolfSSL_set_fd(self.native_object, self.fileno())
|
||||||
|
if ret != _SSL_SUCCESS:
|
||||||
|
self._release_native_object()
|
||||||
|
raise ValueError("Unnable to set fd to ssl object")
|
||||||
|
|
||||||
|
if connected:
|
||||||
|
try:
|
||||||
|
if do_handshake_on_connect:
|
||||||
|
self.do_handshake()
|
||||||
|
except:
|
||||||
|
self._release_native_object()
|
||||||
|
self.close()
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
self._release_native_object()
|
||||||
|
|
||||||
|
|
||||||
|
def _release_native_object(self):
|
||||||
|
if getattr(self, 'native_object', _ffi.NULL) != _ffi.NULL:
|
||||||
|
_lib.wolfSSL_CTX_free(self.native_object)
|
||||||
|
self.native_object = _ffi.NULL
|
||||||
|
|
||||||
|
|
||||||
|
@property
|
||||||
|
def context(self):
|
||||||
|
"""
|
||||||
|
Returns the context used by this object.
|
||||||
|
"""
|
||||||
|
return self._context
|
||||||
|
|
||||||
|
|
||||||
|
def dup(self):
|
||||||
|
raise NotImplementedError("Can't dup() %s instances" %
|
||||||
|
self.__class__.__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def _check_closed(self, call=None):
|
||||||
|
if self.native_object == _ffi.NULL:
|
||||||
|
raise ValueError("%s on closed or unwrapped secure channel" % call)
|
||||||
|
|
||||||
|
def _check_connected(self):
|
||||||
|
if not self._connected:
|
||||||
|
# getpeername() will raise ENOTCONN if the socket is really
|
||||||
|
# not connected; note that we can be connected even without
|
||||||
|
# _connected being set, e.g. if connect() first returned
|
||||||
|
# EAGAIN.
|
||||||
|
self.getpeername()
|
||||||
|
|
||||||
|
|
||||||
|
def write(self, data):
|
||||||
|
"""
|
||||||
|
Write DATA to the underlying secure channel.
|
||||||
|
Returns number of bytes of DATA actually transmitted.
|
||||||
|
"""
|
||||||
|
self._check_closed("write")
|
||||||
|
self._check_connected()
|
||||||
|
|
||||||
|
data = t2b(data)
|
||||||
|
|
||||||
|
return _lib.wolfSSL_write(self.native_object, data, len(data))
|
||||||
|
|
||||||
|
|
||||||
|
def send(self, data, flags=0):
|
||||||
|
if flags != 0:
|
||||||
|
raise NotImplementedError("non-zero flags not allowed in calls to "
|
||||||
|
"send() on %s" % self.__class__)
|
||||||
|
|
||||||
|
return self.write(data)
|
||||||
|
|
||||||
|
|
||||||
|
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:
|
||||||
|
sent += self.write(data[sent:])
|
||||||
|
|
||||||
|
return sent
|
||||||
|
|
||||||
|
|
||||||
|
def sendto(self, data, flags_or_addr, addr=None):
|
||||||
|
# Ensure programs don't send unencrypted data trying to use this method
|
||||||
|
raise NotImplementedError("sendto not allowed on instances "
|
||||||
|
"of %s" % self.__class__)
|
||||||
|
|
||||||
|
|
||||||
|
def sendmsg(self, *args, **kwargs):
|
||||||
|
# Ensure programs don't send unencrypted data trying to use this method
|
||||||
|
raise NotImplementedError("sendmsg not allowed on instances "
|
||||||
|
"of %s" % self.__class__)
|
||||||
|
|
||||||
|
|
||||||
|
def sendfile(self, file, offset=0, count=None):
|
||||||
|
# Ensure programs don't send unencrypted files trying to use this method
|
||||||
|
raise NotImplementedError("sendfile not allowed on instances "
|
||||||
|
"of %s" % self.__class__)
|
||||||
|
|
||||||
|
|
||||||
|
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 recv(self, length=1024, flags=0):
|
||||||
|
if flags != 0:
|
||||||
|
raise NotImplementedError("non-zero flags not allowed in calls to "
|
||||||
|
"recv() on %s" % self.__class__)
|
||||||
|
|
||||||
|
return self.read(self, length)
|
||||||
|
|
||||||
|
|
||||||
|
def recv_into(self, buffer, nbytes=None, flags=0):
|
||||||
|
raise NotImplementedError("recv_into not allowed on instances "
|
||||||
|
"of %s" % self.__class__)
|
||||||
|
|
||||||
|
|
||||||
|
def recvfrom(self, length=1024, flags=0):
|
||||||
|
# Ensure programs don't receive encrypted data trying to use this method
|
||||||
|
raise NotImplementedError("recvfrom not allowed on instances "
|
||||||
|
"of %s" % self.__class__)
|
||||||
|
|
||||||
|
|
||||||
|
def recvfrom_into(self, buffer, nbytes=None, flags=0):
|
||||||
|
# Ensure programs don't receive encrypted data trying to use this method
|
||||||
|
raise NotImplementedError("recvfrom_into not allowed on instances "
|
||||||
|
"of %s" % self.__class__)
|
||||||
|
|
||||||
|
|
||||||
|
def recvmsg(self, *args, **kwargs):
|
||||||
|
raise NotImplementedError("recvmsg not allowed on instances of %s" %
|
||||||
|
self.__class__)
|
||||||
|
|
||||||
|
|
||||||
|
def recvmsg_into(self, *args, **kwargs):
|
||||||
|
raise NotImplementedError("recvmsg_into not allowed on instances of "
|
||||||
|
"%s" % self.__class__)
|
||||||
|
|
||||||
|
|
||||||
|
def shutdown(self, how):
|
||||||
|
if self.native_object != _ffi.NULL:
|
||||||
|
_lib.wolfSSL_shutdown(self.native_object)
|
||||||
|
self._release_native_object()
|
||||||
|
socket.shutdown(self, how)
|
||||||
|
|
||||||
|
|
||||||
|
def unwrap(self):
|
||||||
|
"""
|
||||||
|
Unwraps the underlying OS socket from the SSL/TLS connection.
|
||||||
|
Returns the wrapped OS socket.
|
||||||
|
"""
|
||||||
|
if self.native_object != _ffi.NULL:
|
||||||
|
_lib.wolfSSL_set_fd(self.native_object, -1)
|
||||||
|
|
||||||
|
sock = socket(family=self.family,
|
||||||
|
sock_type=self.type,
|
||||||
|
proto=self.proto,
|
||||||
|
fileno=self.fileno())
|
||||||
|
sock.settimeout(self.gettimeout())
|
||||||
|
self.detach()
|
||||||
|
|
||||||
|
return sock
|
||||||
|
|
||||||
|
|
||||||
|
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 _real_connect(self, addr, connect_ex):
|
||||||
|
if self.server_side:
|
||||||
|
raise ValueError("can't connect in server-side mode")
|
||||||
|
|
||||||
|
# Here we assume that the socket is client-side, and not
|
||||||
|
# connected at the time of the call. We connect it, then wrap it.
|
||||||
|
if self._connected:
|
||||||
|
raise ValueError("attempt to connect already-connected SSLSocket!")
|
||||||
|
|
||||||
|
if connect_ex:
|
||||||
|
err = socket.connect_ex(self, addr)
|
||||||
|
else:
|
||||||
|
err = 0
|
||||||
|
socket.connect(self, addr)
|
||||||
|
|
||||||
|
if err == 0:
|
||||||
|
self._connected = True
|
||||||
|
if self.do_handshake_on_connect:
|
||||||
|
self.do_handshake()
|
||||||
|
|
||||||
|
return err
|
||||||
|
|
||||||
|
|
||||||
|
def connect(self, addr):
|
||||||
|
"""
|
||||||
|
Connects to remote ADDR, and then wraps the connection in a secure
|
||||||
|
channel.
|
||||||
|
"""
|
||||||
|
self._real_connect(addr, False)
|
||||||
|
|
||||||
|
|
||||||
|
def connect_ex(self, addr):
|
||||||
|
"""
|
||||||
|
Connects to remote ADDR, and then wraps the connection in a secure
|
||||||
|
channel.
|
||||||
|
"""
|
||||||
|
return self._real_connect(addr, True)
|
||||||
|
|
||||||
|
|
||||||
|
def accept(self):
|
||||||
|
"""
|
||||||
|
Accepts a new connection from a remote client, and returns a tuple
|
||||||
|
containing that new connection wrapped with a server-side secure
|
||||||
|
channel, and the address of the remote client.
|
||||||
|
"""
|
||||||
|
if not self.server_side:
|
||||||
|
raise ValueError("can't accept in client-side mode")
|
||||||
|
|
||||||
|
newsock, addr = socket.accept(self)
|
||||||
|
newsock = self.context.wrap_socket(
|
||||||
|
newsock,
|
||||||
|
do_handshake_on_connect=self.do_handshake_on_connect,
|
||||||
|
suppress_ragged_eofs=self.suppress_ragged_eofs,
|
||||||
|
server_side=True)
|
||||||
|
|
||||||
|
return newsock, addr
|
||||||
|
|
||||||
|
|
||||||
|
def wrap_socket(sock, keyfile=None, certfile=None, server_side=False,
|
||||||
|
cert_reqs=CERT_NONE, ssl_version=PROTOCOL_TLS, ca_certs=None,
|
||||||
|
do_handshake_on_connect=True, suppress_ragged_eofs=True,
|
||||||
|
ciphers=None):
|
||||||
|
"""
|
||||||
|
Takes an instance sock of socket.socket, and returns an instance of
|
||||||
|
wolfssl.SSLSocket, wraping the underlying socket in an SSL context.
|
||||||
|
|
||||||
|
The sock parameter must be a SOCK_STREAM socket; other socket types are
|
||||||
|
unsupported.
|
||||||
|
|
||||||
|
The keyfile and certfile parameters specify optional files whith proper
|
||||||
|
key and the certificates used to identify the local side of the connection.
|
||||||
|
|
||||||
|
The parameter server_side is a boolean which identifies whether server-side
|
||||||
|
or client-side behavior is desired from this socket.
|
||||||
|
|
||||||
|
The parameter cert_reqs specifies whether a certificate is required from the
|
||||||
|
other side of the connection, and whether it will be validated if provided.
|
||||||
|
It must be one of the three values:
|
||||||
|
|
||||||
|
* CERT_NONE (certificates ignored)
|
||||||
|
* CERT_OPTIONAL (not required, but validated if provided)
|
||||||
|
* CERT_REQUIRED (required and validated)
|
||||||
|
|
||||||
|
If the value of this parameter is not CERT_NONE, then the ca_certs parameter
|
||||||
|
must point to a file of CA certificates.
|
||||||
|
|
||||||
|
The ca_certs file contains a set of concatenated “certification authority”
|
||||||
|
certificates, which are used to validate certificates passed from the other
|
||||||
|
end of the connection.
|
||||||
|
|
||||||
|
The parameter ssl_version specifies which version of the SSL protocol to
|
||||||
|
use. Typically, the server chooses a particular protocol version, and the
|
||||||
|
client must adapt to the server’s choice. Most of the versions are not
|
||||||
|
interoperable with the other versions. If not specified, the default is
|
||||||
|
PROTOCOL_TLS; it provides the most compatibility with other versions.
|
||||||
|
|
||||||
|
Here’s a table showing which versions in a client (down the side) can
|
||||||
|
connect to which versions in a server (along the top):
|
||||||
|
|
||||||
|
+------------------+-------+-----+-------+---------+---------+
|
||||||
|
| client \\ server | SSLv3 | TLS | TLSv1 | TLSv1.1 | TLSv1.2 |
|
||||||
|
+------------------+-------+-----+-------+---------+---------+
|
||||||
|
| SSLv3 | yes | yes | no | no | no |
|
||||||
|
+------------------+-------+-----+-------+---------+---------+
|
||||||
|
| TLS (SSLv23) | yes | yes | yes | yes | yes |
|
||||||
|
+------------------+-------+-----+-------+---------+---------+
|
||||||
|
| TLSv1 | no | yes | yes | no | no |
|
||||||
|
+------------------+-------+-----+-------+---------+---------+
|
||||||
|
| TLSv1.1 | no | yes | no | yes | no |
|
||||||
|
+------------------+-------+-----+-------+---------+---------+
|
||||||
|
| TLSv1.2 | no | yes | no | no | yes |
|
||||||
|
+------------------+-------+-----+-------+---------+---------+
|
||||||
|
|
||||||
|
Note:
|
||||||
|
Which connections succeed will vary depending on the versions of the ssl
|
||||||
|
providers on both sides of the communication.
|
||||||
|
|
||||||
|
The ciphers parameter sets the available ciphers for this SSL object. It
|
||||||
|
should be a string in the wolfSSL cipher list format.
|
||||||
|
|
||||||
|
The parameter do_handshake_on_connect specifies whether to do the SSL
|
||||||
|
handshake automatically after doing a socket.connect(), or whether the
|
||||||
|
application program will call it explicitly, by invoking the
|
||||||
|
SSLSocket.do_handshake() method. Calling SSLSocket.do_handshake() explicitly
|
||||||
|
gives the program control over the blocking behavior of the socket I/O
|
||||||
|
involved in the handshake.
|
||||||
|
|
||||||
|
The parameter suppress_ragged_eofs is not supported yet.
|
||||||
|
"""
|
||||||
|
return SSLSocket(sock=sock, keyfile=keyfile, certfile=certfile,
|
||||||
|
server_side=server_side, cert_reqs=cert_reqs,
|
||||||
|
ssl_version=ssl_version, ca_certs=ca_certs,
|
||||||
|
do_handshake_on_connect=do_handshake_on_connect,
|
||||||
|
suppress_ragged_eofs=suppress_ragged_eofs,
|
||||||
|
ciphers=ciphers)
|
34
wrapper/python/wolfssl/src/wolfssl/_memory.py
Normal file
34
wrapper/python/wolfssl/src/wolfssl/_memory.py
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# _memory.py
|
||||||
|
#
|
||||||
|
# Copyright (C) 2006-2017 wolfSSL Inc.
|
||||||
|
#
|
||||||
|
# This file is part of wolfSSL. (formerly known as CyaSSL)
|
||||||
|
#
|
||||||
|
# wolfSSL is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# wolfSSL is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
|
||||||
|
# pylint: disable=missing-docstring
|
||||||
|
|
||||||
|
try:
|
||||||
|
from wolfssl._ffi import ffi as _ffi
|
||||||
|
from wolfssl._ffi import lib as _lib
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
_DYNAMIC_TYPE_METHOD = 11
|
||||||
|
|
||||||
|
def _native_free(native_object, dynamic_type):
|
||||||
|
_lib.wolfSSL_Free(native_object, _ffi.NULL, dynamic_type)
|
82
wrapper/python/wolfssl/src/wolfssl/_methods.py
Normal file
82
wrapper/python/wolfssl/src/wolfssl/_methods.py
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# _methods.py
|
||||||
|
#
|
||||||
|
# Copyright (C) 2006-2017 wolfSSL Inc.
|
||||||
|
#
|
||||||
|
# This file is part of wolfSSL. (formerly known as CyaSSL)
|
||||||
|
#
|
||||||
|
# wolfSSL is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# wolfSSL is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
|
||||||
|
# pylint: disable=missing-docstring, invalid-name
|
||||||
|
|
||||||
|
try:
|
||||||
|
from wolfssl._ffi import ffi as _ffi
|
||||||
|
from wolfssl._ffi import lib as _lib
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
from wolfssl._memory import (
|
||||||
|
_native_free, _DYNAMIC_TYPE_METHOD
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
PROTOCOL_SSLv23 = 1
|
||||||
|
PROTOCOL_SSLv3 = 2
|
||||||
|
PROTOCOL_TLS = 1
|
||||||
|
PROTOCOL_TLSv1 = 3
|
||||||
|
PROTOCOL_TLSv1_1 = 4
|
||||||
|
PROTOCOL_TLSv1_2 = 5
|
||||||
|
|
||||||
|
_PROTOCOL_LIST = [PROTOCOL_SSLv23, PROTOCOL_SSLv3, PROTOCOL_TLS,
|
||||||
|
PROTOCOL_TLSv1, PROTOCOL_TLSv1_1, PROTOCOL_TLSv1_2]
|
||||||
|
|
||||||
|
|
||||||
|
class WolfSSLMethod(object):
|
||||||
|
"""
|
||||||
|
An SSLMethod holds SSL-related configuration options such as
|
||||||
|
protocol version and communication side.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, protocol, server_side):
|
||||||
|
if protocol not in _PROTOCOL_LIST:
|
||||||
|
raise ValueError("this protocol is not supported")
|
||||||
|
|
||||||
|
elif protocol == PROTOCOL_SSLv3:
|
||||||
|
raise ValueError("this protocol is not supported")
|
||||||
|
|
||||||
|
elif protocol == PROTOCOL_TLSv1:
|
||||||
|
raise ValueError("this protocol is not supported")
|
||||||
|
|
||||||
|
elif protocol == PROTOCOL_TLSv1_1:
|
||||||
|
raise ValueError("this protocol is not supported")
|
||||||
|
|
||||||
|
elif protocol == PROTOCOL_TLSv1_2:
|
||||||
|
self.native_object = \
|
||||||
|
_lib.wolfTLSv1_2_server_method() if server_side else \
|
||||||
|
_lib.wolfTLSv1_2_client_method()
|
||||||
|
|
||||||
|
elif protocol in [PROTOCOL_SSLv23, PROTOCOL_TLS]:
|
||||||
|
self.native_object = \
|
||||||
|
_lib.wolfSSLv23_server_method() if server_side else \
|
||||||
|
_lib.wolfSSLv23_client_method()
|
||||||
|
|
||||||
|
if self.native_object == _ffi.NULL:
|
||||||
|
raise MemoryError("Unnable to allocate method object")
|
||||||
|
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
if getattr(self, 'native_object', _ffi.NULL) != _ffi.NULL:
|
||||||
|
_native_free(self.native_object, _DYNAMIC_TYPE_METHOD)
|
79
wrapper/python/wolfssl/src/wolfssl/build_ffi.py
Normal file
79
wrapper/python/wolfssl/src/wolfssl/build_ffi.py
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# build_ffi.py
|
||||||
|
#
|
||||||
|
# Copyright (C) 2006-2017 wolfSSL Inc.
|
||||||
|
#
|
||||||
|
# This file is part of wolfSSL. (formerly known as CyaSSL)
|
||||||
|
#
|
||||||
|
# wolfSSL is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# wolfSSL is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
|
||||||
|
# pylint: disable=missing-docstring, invalid-name
|
||||||
|
|
||||||
|
from cffi import FFI
|
||||||
|
|
||||||
|
ffi = FFI()
|
||||||
|
|
||||||
|
ffi.set_source(
|
||||||
|
"wolfssl._ffi",
|
||||||
|
"""
|
||||||
|
#include <wolfssl/options.h>
|
||||||
|
#include <wolfssl/ssl.h>
|
||||||
|
|
||||||
|
void wolfSSL_Free(void *ptr, void* heap, int type);
|
||||||
|
""",
|
||||||
|
include_dirs=["/usr/local/include"],
|
||||||
|
library_dirs=["/usr/local/lib"],
|
||||||
|
libraries=["wolfssl"],
|
||||||
|
)
|
||||||
|
|
||||||
|
ffi.cdef(
|
||||||
|
"""
|
||||||
|
typedef unsigned char byte;
|
||||||
|
typedef unsigned int word32;
|
||||||
|
|
||||||
|
void wolfSSL_Free(void*, void*, int);
|
||||||
|
|
||||||
|
void* wolfSSLv23_server_method(void);
|
||||||
|
void* wolfSSLv23_client_method(void);
|
||||||
|
void* wolfTLSv1_2_server_method(void);
|
||||||
|
void* wolfTLSv1_2_client_method(void);
|
||||||
|
|
||||||
|
void* wolfSSL_CTX_new(void*);
|
||||||
|
void wolfSSL_CTX_free(void*);
|
||||||
|
|
||||||
|
void wolfSSL_CTX_set_verify(void*, int, void*);
|
||||||
|
int wolfSSL_CTX_set_cipher_list(void*, const char*);
|
||||||
|
int wolfSSL_CTX_use_PrivateKey_file(void*, const char*, int);
|
||||||
|
int wolfSSL_CTX_load_verify_locations(void*, const char*, const char*);
|
||||||
|
int wolfSSL_CTX_load_verify_buffer(void*, const unsigned char*, long, int);
|
||||||
|
int wolfSSL_CTX_use_certificate_chain_file(void*, const char *);
|
||||||
|
int wolfSSL_CTX_UseSupportedCurve(void*, short);
|
||||||
|
|
||||||
|
|
||||||
|
void* wolfSSL_new(void*);
|
||||||
|
void wolfSSL_free(void*);
|
||||||
|
|
||||||
|
int wolfSSL_set_fd(void*, int);
|
||||||
|
int wolfSSL_get_error(void*, int);
|
||||||
|
int wolfSSL_negotiate(void*);
|
||||||
|
int wolfSSL_write(void*, const void*, int);
|
||||||
|
int wolfSSL_read(void*, void*, int);
|
||||||
|
int wolfSSL_shutdown(void*);
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
ffi.compile(verbose=1)
|
88
wrapper/python/wolfssl/src/wolfssl/exceptions.py
Normal file
88
wrapper/python/wolfssl/src/wolfssl/exceptions.py
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# exceptions.py
|
||||||
|
#
|
||||||
|
# Copyright (C) 2006-2017 wolfSSL Inc.
|
||||||
|
#
|
||||||
|
# This file is part of wolfSSL. (formerly known as CyaSSL)
|
||||||
|
#
|
||||||
|
# wolfSSL is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# wolfSSL is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
|
||||||
|
# pylint: disable=missing-docstring
|
||||||
|
|
||||||
|
from socket import error as socket_error
|
||||||
|
|
||||||
|
|
||||||
|
class SSLError(socket_error):
|
||||||
|
"""
|
||||||
|
Raised to signal an error from the wolfSSL's SSL/TLS library. This signifies
|
||||||
|
some problem in the higher-level encryption and authentication layer that's
|
||||||
|
superimposed on the underlying network connection. This error is a subtype
|
||||||
|
of socket.error, which in turn is a subtype of IOError. The error code and
|
||||||
|
message of SSLError instances are provided by the wolfSSL library.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class SSLZeroReturnError(SSLError):
|
||||||
|
"""
|
||||||
|
A subclass of SSLError raised when trying to read or write and the SSL
|
||||||
|
connection has been closed cleanly. Note that this doesn't mean that the
|
||||||
|
underlying transport (read TCP) has been closed.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class SSLWantReadError(SSLError):
|
||||||
|
"""
|
||||||
|
A subclass of SSLError raised by a non-blocking SSL socket when trying to
|
||||||
|
read or write data, but more data needs to be received on the underlying TCP
|
||||||
|
transport before the request can be fulfilled.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class SSLWantWriteError(SSLError):
|
||||||
|
"""
|
||||||
|
A subclass of SSLError raised by a non-blocking SSL socket when trying to
|
||||||
|
read or write data, but more data needs to be sent on the underlying TCP
|
||||||
|
transport before the request can be fulfilled.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class SSLSyscallError(SSLError):
|
||||||
|
"""
|
||||||
|
A subclass of SSLError raised when a system error was encountered while
|
||||||
|
trying to fulfill an operation on a SSL socket. Unfortunately, there is no
|
||||||
|
easy way to inspect the original errno number.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class SSLEOFError(SSLError):
|
||||||
|
"""
|
||||||
|
A subclass of SSLError raised when the SSL connection has been terminated
|
||||||
|
abruptly. Generally, you shouldn't try to reuse the underlying transport
|
||||||
|
when this error is encountered.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
class CertificateError(ValueError):
|
||||||
|
"""
|
||||||
|
Raised to signal an error with a certificate (such as mismatching hostname).
|
||||||
|
Certificate errors detected by wolfSSL, though, raise an SSLError.
|
||||||
|
"""
|
||||||
|
pass
|
38
wrapper/python/wolfssl/src/wolfssl/utils.py
Normal file
38
wrapper/python/wolfssl/src/wolfssl/utils.py
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# utils.py
|
||||||
|
#
|
||||||
|
# Copyright (C) 2006-2017 wolfSSL Inc.
|
||||||
|
#
|
||||||
|
# This file is part of wolfSSL. (formerly known as CyaSSL)
|
||||||
|
#
|
||||||
|
# wolfSSL is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# wolfSSL is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
|
||||||
|
# pylint: disable=missing-docstring, unused-import, undefined-variable
|
||||||
|
|
||||||
|
import sys
|
||||||
|
from binascii import hexlify as b2h, unhexlify as h2b
|
||||||
|
|
||||||
|
_PY3 = sys.version_info[0] == 3
|
||||||
|
_TEXT_TYPE = str if _PY3 else unicode
|
||||||
|
_BINARY_TYPE = bytes if _PY3 else str
|
||||||
|
|
||||||
|
def t2b(string):
|
||||||
|
"""
|
||||||
|
Converts text to bynary.
|
||||||
|
"""
|
||||||
|
if isinstance(string, _BINARY_TYPE):
|
||||||
|
return string
|
||||||
|
return _TEXT_TYPE(string).encode("utf-8")
|
46
wrapper/python/wolfssl/test/conftest.py
Normal file
46
wrapper/python/wolfssl/test/conftest.py
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# conftest.py
|
||||||
|
#
|
||||||
|
# Copyright (C) 2006-2017 wolfSSL Inc.
|
||||||
|
#
|
||||||
|
# This file is part of wolfSSL. (formerly known as CyaSSL)
|
||||||
|
#
|
||||||
|
# wolfSSL is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# wolfSSL is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
|
||||||
|
# pylint: disable=missing-docstring, redefined-outer-name
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import ssl
|
||||||
|
import wolfssl
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def tcp_socket():
|
||||||
|
import socket
|
||||||
|
from contextlib import closing
|
||||||
|
|
||||||
|
with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock:
|
||||||
|
yield sock
|
||||||
|
|
||||||
|
@pytest.fixture(
|
||||||
|
params=[ssl, wolfssl] if sys.version_info.major == 3 else [wolfssl],
|
||||||
|
ids=["ssl", "wolfssl"] if sys.version_info.major == 3 else ["wolfssl"])
|
||||||
|
def ssl_provider(request):
|
||||||
|
return request.param
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def ssl_context(ssl_provider):
|
||||||
|
return ssl_provider.SSLContext(ssl_provider.PROTOCOL_SSLv23)
|
65
wrapper/python/wolfssl/test/test_client.py
Normal file
65
wrapper/python/wolfssl/test/test_client.py
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# test_client.py
|
||||||
|
#
|
||||||
|
# Copyright (C) 2006-2017 wolfSSL Inc.
|
||||||
|
#
|
||||||
|
# This file is part of wolfSSL. (formerly known as CyaSSL)
|
||||||
|
#
|
||||||
|
# wolfSSL is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# wolfSSL is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
|
||||||
|
# pylint: disable=missing-docstring, invalid-name, import-error
|
||||||
|
# pylint: disable=redefined-outer-name
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
HOST = "www.python.org"
|
||||||
|
PORT = 443
|
||||||
|
CA_CERTS = "certs/ca-digicert-ev.pem"
|
||||||
|
|
||||||
|
@pytest.fixture(
|
||||||
|
params=["wrap_socket", "wrap_socket_with_ca",
|
||||||
|
"wrap_socket_from_context", "ssl_socket"])
|
||||||
|
def secure_socket(request, ssl_provider, tcp_socket):
|
||||||
|
sock = None
|
||||||
|
|
||||||
|
if request.param == "wrap_socket":
|
||||||
|
sock = ssl_provider.wrap_socket(tcp_socket)
|
||||||
|
|
||||||
|
elif request.param == "wrap_socket_with_ca":
|
||||||
|
sock = ssl_provider.wrap_socket(
|
||||||
|
tcp_socket, cert_reqs=ssl_provider.CERT_REQUIRED, ca_certs=CA_CERTS)
|
||||||
|
|
||||||
|
elif request.param == "wrap_socket_from_context":
|
||||||
|
ctx = ssl_provider.SSLContext(ssl_provider.PROTOCOL_TLSv1_2)
|
||||||
|
|
||||||
|
ctx.verify_mode = ssl_provider.CERT_REQUIRED
|
||||||
|
ctx.load_verify_locations(CA_CERTS)
|
||||||
|
|
||||||
|
sock = ctx.wrap_socket(tcp_socket)
|
||||||
|
|
||||||
|
elif request.param == "ssl_socket":
|
||||||
|
sock = ssl_provider.SSLSocket(
|
||||||
|
tcp_socket, cert_reqs=ssl_provider.CERT_REQUIRED, ca_certs=CA_CERTS)
|
||||||
|
|
||||||
|
if sock:
|
||||||
|
yield sock
|
||||||
|
sock.close()
|
||||||
|
|
||||||
|
def test_secure_connection(secure_socket):
|
||||||
|
secure_socket.connect((HOST, PORT))
|
||||||
|
|
||||||
|
secure_socket.write(b"GET / HTTP/1.1\n\n")
|
||||||
|
assert secure_socket.read(4) == b"HTTP"
|
65
wrapper/python/wolfssl/test/test_context.py
Normal file
65
wrapper/python/wolfssl/test/test_context.py
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# test_context.py
|
||||||
|
#
|
||||||
|
# Copyright (C) 2006-2017 wolfSSL Inc.
|
||||||
|
#
|
||||||
|
# This file is part of wolfSSL. (formerly known as CyaSSL)
|
||||||
|
#
|
||||||
|
# wolfSSL is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# wolfSSL is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
|
||||||
|
# pylint: disable=missing-docstring, invalid-name, import-error
|
||||||
|
# pylint: disable=redefined-outer-name
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
with open("certs/ca-cert.pem") as ca:
|
||||||
|
_CADATA = ca.read()
|
||||||
|
|
||||||
|
def test_context_creation(ssl_context):
|
||||||
|
assert ssl_context != None
|
||||||
|
|
||||||
|
def test_verify_mode(ssl_provider, ssl_context):
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
ssl_context.verify_mode = -1
|
||||||
|
|
||||||
|
assert ssl_context.verify_mode == ssl_provider.CERT_NONE
|
||||||
|
|
||||||
|
ssl_context.verify_mode = ssl_provider.CERT_REQUIRED
|
||||||
|
assert ssl_context.verify_mode == ssl_provider.CERT_REQUIRED
|
||||||
|
|
||||||
|
def test_set_ciphers(ssl_context):
|
||||||
|
ssl_context.set_ciphers("DHE-RSA-AES256-SHA256")
|
||||||
|
|
||||||
|
with pytest.raises(Exception):
|
||||||
|
ssl_context.set_ciphers("foo")
|
||||||
|
|
||||||
|
def test_load_cert_chain_raises(ssl_context):
|
||||||
|
with pytest.raises(TypeError):
|
||||||
|
ssl_context.load_cert_chain(None)
|
||||||
|
|
||||||
|
def test_load_cert_chain(ssl_context):
|
||||||
|
ssl_context.load_cert_chain("certs/client-cert.pem",
|
||||||
|
"certs/client-key.pem")
|
||||||
|
|
||||||
|
def test_load_verify_locations_raises(ssl_context):
|
||||||
|
with pytest.raises(TypeError):
|
||||||
|
ssl_context.load_verify_locations(None)
|
||||||
|
|
||||||
|
def test_load_verify_locations_with_cafile(ssl_context):
|
||||||
|
ssl_context.load_verify_locations(cafile="certs/ca-cert.pem")
|
||||||
|
|
||||||
|
def test_load_verify_locations_with_cadata(ssl_provider, ssl_context):
|
||||||
|
ssl_context.load_verify_locations(cadata=_CADATA)
|
58
wrapper/python/wolfssl/test/test_methods.py
Normal file
58
wrapper/python/wolfssl/test/test_methods.py
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# test_methods.py
|
||||||
|
#
|
||||||
|
# Copyright (C) 2006-2017 wolfSSL Inc.
|
||||||
|
#
|
||||||
|
# This file is part of wolfSSL. (formerly known as CyaSSL)
|
||||||
|
#
|
||||||
|
# wolfSSL is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# wolfSSL is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
|
||||||
|
# pylint: disable=missing-docstring, redefined-outer-name, import-error
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from wolfssl._methods import (WolfSSLMethod, PROTOCOL_SSLv3, PROTOCOL_SSLv23,
|
||||||
|
PROTOCOL_TLS, PROTOCOL_TLSv1, PROTOCOL_TLSv1_1,
|
||||||
|
PROTOCOL_TLSv1_2)
|
||||||
|
from wolfssl._ffi import ffi as _ffi
|
||||||
|
|
||||||
|
@pytest.fixture(
|
||||||
|
params=[-1, PROTOCOL_SSLv3, PROTOCOL_TLSv1, PROTOCOL_TLSv1_1],
|
||||||
|
ids=["invalid", "SSLv3", "TLSv1", "TLSv1_1"])
|
||||||
|
def unsupported_method(request):
|
||||||
|
yield request.param
|
||||||
|
|
||||||
|
@pytest.fixture(
|
||||||
|
params=[PROTOCOL_SSLv23, PROTOCOL_TLS, PROTOCOL_TLSv1_2],
|
||||||
|
ids=["SSLv23", "TLS", "TLSv1_2"])
|
||||||
|
def supported_method(request):
|
||||||
|
yield request.param
|
||||||
|
|
||||||
|
|
||||||
|
def test_unsupported_method(unsupported_method):
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
WolfSSLMethod(unsupported_method, False)
|
||||||
|
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
WolfSSLMethod(unsupported_method, True)
|
||||||
|
|
||||||
|
def test_supported_method(supported_method):
|
||||||
|
client = WolfSSLMethod(supported_method, False)
|
||||||
|
server = WolfSSLMethod(supported_method, True)
|
||||||
|
|
||||||
|
assert isinstance(client, WolfSSLMethod)
|
||||||
|
assert isinstance(server, WolfSSLMethod)
|
||||||
|
assert client.native_object != _ffi.NULL
|
||||||
|
assert server.native_object != _ffi.NULL
|
7
wrapper/python/wolfssl/tox.ini
Normal file
7
wrapper/python/wolfssl/tox.ini
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
[tox]
|
||||||
|
envlist=py27,py34,py35,py36
|
||||||
|
skip_missing_interpreters=true
|
||||||
|
|
||||||
|
[testenv]
|
||||||
|
deps=-rrequirements-testing.txt
|
||||||
|
commands=py.test test/ {posargs}
|
Reference in New Issue
Block a user