Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PoC: Make it possible to write code that interacts with OpenSSL in Rust #6695

Closed
wants to merge 25 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
37c02ca
Make it possible to write code that interacts with OpenSSL in Rust
messense Dec 3, 2021
accb232
Use the new _openssl submodule to allow running tests
messense Dec 3, 2021
e7d71a3
Use `DEP_OPENSSL_INCLUDE`
messense Dec 12, 2021
71c8424
Generate `_openssl.c` in Rust's `OUT_DIR`
messense Dec 12, 2021
e5f9407
Fix PYTHONPATH
messense Dec 13, 2021
68214d4
Force OpenSSL link
messense Dec 13, 2021
d68c685
Use OPENSSL_DIR instead of LDFLAGS
messense Dec 13, 2021
d07fd9a
Fix a clippy warning
messense Dec 13, 2021
b895314
Move finding python include dir to Rust side
messense Dec 13, 2021
add33fa
CI: set OPENSSL_DIR for Windows
messense Dec 13, 2021
8a6f0f9
Print stdout and stderr when build_openssl.py fails
messense Dec 13, 2021
c11218a
Try to fix Windows
messense Dec 13, 2021
b087223
Set rpath with RUSTFLAGS
messense Dec 13, 2021
1ef6259
Install cffi in Rust Coverage job
messense Dec 13, 2021
65340cb
Move extra compile args to Rust side
messense Dec 13, 2021
a9aa151
Link against clang runtime on static builds on macOS
messense Dec 14, 2021
e36ba2b
Bump MSRV to 1.48.0
messense Dec 14, 2021
21208ff
Define `Py_LIMITED_API`
messense Dec 14, 2021
916716c
Use OPENSSL_DIR for zuul wheel build
messense Dec 14, 2021
a114535
Install pkg-config in zuul
messense Dec 14, 2021
2eea530
Try to fix mypy error
messense Dec 15, 2021
1377cee
Use git dependency for openssl crate
messense Dec 27, 2021
9518ea1
Try to fix circleci build failures
messense Dec 28, 2021
0604d80
Try cffi embedding API
messense Dec 28, 2021
50a751a
Define WIN32_LEAN_AND_MEAN in Rust side
messense Dec 28, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions .circleci/build-wheel.sh
Expand Up @@ -23,8 +23,8 @@ if [[ "${PYBIN}" =~ $REGEX ]]; then
PY_LIMITED_API="--py-limited-api=cp3${BASH_REMATCH[1]}"
fi

LDFLAGS="-L/opt/pyca/cryptography/openssl/lib" \
CFLAGS="-I/opt/pyca/cryptography/openssl/include -Wl,--exclude-libs,ALL" \
OPENSSL_DIR="/opt/pyca/cryptography/openssl" \
RUSTFLAGS="-Clink-arg=-Wl,--exclude-libs,ALL" \
../../.venv/bin/python setup.py bdist_wheel "$PY_LIMITED_API"

auditwheel repair --plat "${PLATFORM}" -w wheelhouse/ dist/cryptography*.whl
Expand Down
18 changes: 9 additions & 9 deletions .github/workflows/ci.yml
Expand Up @@ -110,8 +110,9 @@ jobs:
if: matrix.PYTHON.OPENSSL && steps.ossl-cache.outputs.cache-hit != 'true'
- name: Set CFLAGS/LDFLAGS
run: |
echo "CFLAGS=${CFLAGS} -Werror=implicit-function-declaration -I${OSSL_PATH}/include" >> $GITHUB_ENV
echo "LDFLAGS=${LDFLAGS} -L${OSSL_PATH}/lib -L${OSSL_PATH}/lib64 -Wl,-rpath=${OSSL_PATH}/lib -Wl,-rpath=${OSSL_PATH}/lib64" >> $GITHUB_ENV
echo "OPENSSL_DIR=${OSSL_PATH}" >> $GITHUB_ENV
echo "CFLAGS=${CFLAGS} -Werror=implicit-function-declaration" >> $GITHUB_ENV
echo "RUSTFLAGS=-Clink-arg=-Wl,-rpath=${OSSL_PATH}/lib -Clink-arg=-Wl,-rpath=${OSSL_PATH}/lib64" >> $GITHUB_ENV
if: matrix.PYTHON.OPENSSL
- name: Tests
run: |
Expand Down Expand Up @@ -188,8 +189,7 @@ jobs:
- {VERSION: "3.9", TOXENV: "py39"}
RUST:
# Cover MSRV (and likely next MSRV) and in-dev versions
- 1.41.0
- 1.45.0
- 1.48.0
- beta
name: "${{ matrix.PYTHON.TOXENV }} with Rust ${{ matrix.RUST }}"
timeout-minutes: 15
Expand Down Expand Up @@ -284,7 +284,7 @@ jobs:
repository: "google/wycheproof"
path: "wycheproof"
ref: "master"
- run: python -m pip install tox coverage
- run: python -m pip install tox coverage cffi
- name: Tests
run: |
tox -r -- --color=yes --wycheproof-root=wycheproof
Expand Down Expand Up @@ -381,8 +381,9 @@ jobs:
- name: Tests
run: |
CRYPTOGRAPHY_SUPPRESS_LINK_FLAGS=1 \
LDFLAGS="${HOME}/openssl-macos-x86-64/lib/libcrypto.a ${HOME}/openssl-macos-x86-64/lib/libssl.a" \
CFLAGS="-I${HOME}/openssl-macos-x86-64/include -Werror -Wno-error=deprecated-declarations -Wno-error=incompatible-pointer-types-discards-qualifiers -Wno-error=unused-function -Wno-error=unused-command-line-argument -mmacosx-version-min=10.10 -march=core2 $EXTRA_CFLAGS" \
OPENSSL_DIR="${HOME}/openssl-macos-x86-64" \
OPENSSL_STATIC=1 \
CFLAGS="-Werror -Wno-error=deprecated-declarations -Wno-error=incompatible-pointer-types-discards-qualifiers -Wno-error=unused-function -Wno-error=unused-command-line-argument -mmacosx-version-min=10.10 -march=core2 $EXTRA_CFLAGS" \
tox -r -- --color=yes --wycheproof-root=wycheproof
env:
TOXENV: ${{ matrix.PYTHON.TOXENV }}
Expand Down Expand Up @@ -442,8 +443,7 @@ jobs:
- name: Download OpenSSL
run: |
python .github/workflows/download_openssl.py windows openssl-${{ matrix.WINDOWS.WINDOWS }}-${{ matrix.PYTHON.MSVC_VERSION }}
echo "INCLUDE=C:/openssl-${{ matrix.WINDOWS.WINDOWS }}-${{ matrix.PYTHON.MSVC_VERSION }}/include;$INCLUDE" >> $GITHUB_ENV
echo "LIB=C:/openssl-${{ matrix.WINDOWS.WINDOWS }}-${{ matrix.PYTHON.MSVC_VERSION }}/lib;$LIB" >> $GITHUB_ENV
echo "OPENSSL_DIR=C:/openssl-${{ matrix.WINDOWS.WINDOWS }}-${{ matrix.PYTHON.MSVC_VERSION }}" >> $GITHUB_ENV
echo "CL=${{ matrix.PYTHON.CL_FLAGS }}" >> $GITHUB_ENV
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Expand Down
1 change: 1 addition & 0 deletions .zuul.playbooks/playbooks/tox/pre.yaml
Expand Up @@ -17,6 +17,7 @@
- libssl-dev
- libffi-dev
- python3-dev
- pkg-config
become: yes
when: ansible_distribution in ['Debian', 'Ubuntu']

Expand Down
Expand Up @@ -20,8 +20,8 @@ for P in ${PYTHONS}; do
PY_LIMITED_API="--py-limited-api=cp3${BASH_REMATCH[1]}"
fi

LDFLAGS="-L/opt/pyca/cryptography/openssl/lib" \
CFLAGS="-I/opt/pyca/cryptography/openssl/include -Wl,--exclude-libs,ALL" \
OPENSSL_DIR="/opt/pyca/cryptography/openssl" \
RUSTFLAGS="-Clink-arg=-Wl,--exclude-libs,ALL" \
.venv/bin/python setup.py bdist_wheel $PY_LIMITED_API

auditwheel repair --plat ${PLAT} -w wheelhouse/ dist/cryptography*.whl
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Expand Up @@ -30,7 +30,7 @@ warn_unused_ignores = true

[[tool.mypy.overrides]]
module = [
"cryptography.hazmat.bindings._openssl",
"cryptography.hazmat.bindings._rust._openssl",
"pretend"
]
ignore_missing_imports = true
3 changes: 0 additions & 3 deletions setup.py
Expand Up @@ -37,9 +37,6 @@
try:
# See setup.cfg for most of the config metadata.
setup(
cffi_modules=[
"src/_cffi_src/build_openssl.py:ffi",
],
rust_extensions=[
RustExtension(
"_rust",
Expand Down
12 changes: 12 additions & 0 deletions src/_cffi_src/build_openssl.py
Expand Up @@ -112,3 +112,15 @@ def _extra_compile_args(platform):
libraries=_get_openssl_libraries(sys.platform),
extra_compile_args=_extra_compile_args(sys.platform),
)

if __name__ == "__main__":
out_dir = os.getenv("OUT_DIR")
module_name, source, source_extension, kwds = ffi._assigned_source
c_file = os.path.join(out_dir, module_name + source_extension)
ffi.embedding_api(
"""
extern "Python" void _this_is_not_used(void);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add a comment explaining what this is for?

"""
)
ffi.embedding_init_code("")
ffi.emit_c_code(c_file)
2 changes: 2 additions & 0 deletions src/_cffi_src/openssl/cryptography.py
Expand Up @@ -32,7 +32,9 @@
#include <openssl/e_os2.h>
#endif
#if defined(_WIN32)
#if !defined(WIN32_LEAN_AND_MEAN)
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <Wincrypt.h>
#include <Winsock2.h>
Expand Down
6 changes: 6 additions & 0 deletions src/_cffi_src/utils.py
Expand Up @@ -73,6 +73,12 @@ def build_ffi(
verify_source += '\n#define CRYPTOGRAPHY_PACKAGE_VERSION "{}"'.format(
about["__version__"]
)
verify_source += r"""

int make_cryptography_openssl_module(void) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's name this Cryptography_make_openssl_module(), which is the prefix we generally use.

return cffi_start_python();
}
"""
ffi.cdef(cdef_source)
ffi.set_source(
module_name,
Expand Down
1 change: 1 addition & 0 deletions src/cryptography/hazmat/bindings/_rust/_openssl.pyi
@@ -0,0 +1 @@
# An empty file to make mypy recognize this module
4 changes: 3 additions & 1 deletion src/cryptography/hazmat/bindings/openssl/binding.py
Expand Up @@ -11,9 +11,11 @@
import cryptography
from cryptography import utils
from cryptography.exceptions import InternalError
from cryptography.hazmat.bindings._openssl import ffi, lib
from cryptography.hazmat.bindings._rust import _openssl
from cryptography.hazmat.bindings.openssl._conditional import CONDITIONAL_NAMES

ffi = _openssl.ffi # type: ignore
lib = _openssl.lib # type: ignore
Comment on lines +17 to +18
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What actually uses these? Theoretically everything should go through a Binding instance.

_OpenSSLErrorWithText = typing.NamedTuple(
"_OpenSSLErrorWithText",
[("code", int), ("lib", int), ("reason", int), ("reason_text", bytes)],
Expand Down
72 changes: 72 additions & 0 deletions src/rust/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions src/rust/Cargo.toml
Expand Up @@ -12,6 +12,11 @@ asn1 = { version = "0.8.7", default-features = false, features = ["derive"] }
pem = "1.0"
chrono = { version = "0.4", default-features = false, features = ["alloc", "clock"] }
ouroboros = "0.13"
openssl = "0.10.38"
openssl-sys = "0.9.72"

[build-dependencies]
cc = "1.0.72"

[features]
extension-module = ["pyo3/extension-module"]
Expand All @@ -24,3 +29,7 @@ crate-type = ["cdylib"]
[profile.release]
lto = "thin"
overflow-checks = true

[patch.crates-io]
openssl-sys = { git = "https://github.com/sfackler/rust-openssl.git" }
openssl = { git = "https://github.com/sfackler/rust-openssl.git" }