Skip to content

Commit

Permalink
Add support for macOS-specific LibreSSL error codes
Browse files Browse the repository at this point in the history
  • Loading branch information
wbond committed Oct 1, 2022
1 parent 222a558 commit 085c63f
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 16 deletions.
22 changes: 21 additions & 1 deletion oscrypto/_openssl/_libssl.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
# coding: utf-8
from __future__ import unicode_literals, division, absolute_import, print_function

from .. import ffi
import re
import sys

from .. import ffi, _backend_config

# Initialize OpenSSL
from ._libcrypto import libcrypto_version_info
Expand All @@ -15,6 +18,7 @@
__all__ = [
'libssl',
'LibsslConst',
'error_code_version_info',
]


Expand Down Expand Up @@ -87,3 +91,19 @@ class LibsslConst():

if libcrypto_version_info >= (1, 1, 0):
LibsslConst.SSL_R_DH_KEY_TOO_SMALL = 394


# The Apple version of libssl seems to have changed various codes for
# some reason, but the rest of the API is still OpenSSL 1.0.1
if sys.platform == 'darwin' and re.match(r'/usr/lib/libssl\.\d', _backend_config().get('libssl_path', '')):
LibsslConst.SSL_F_TLS_PROCESS_SERVER_CERTIFICATE = 7
LibsslConst.SSL_F_SSL3_GET_KEY_EXCHANGE = 9
LibsslConst.SSL_F_SSL3_READ_BYTES = 4
LibsslConst.SSL_F_SSL3_GET_RECORD = 4
LibsslConst.SSL_F_SSL23_GET_SERVER_HELLO = 4
error_code_version_info = (1, 1, 0)
error_code_variant = 'macos'

else:
error_code_version_info = libcrypto_version_info
error_code_variant = 'openssl'
23 changes: 8 additions & 15 deletions oscrypto/_openssl/tls.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import select
import numbers

from ._libssl import libssl, LibsslConst
from ._libssl import error_code_version_info, error_code_variant, libssl, LibsslConst
from ._libcrypto import libcrypto, libcrypto_version_info, handle_openssl_error, peek_openssl_error
from .. import _backend_config
from .._asn1 import Certificate as Asn1Certificate
Expand Down Expand Up @@ -554,7 +554,7 @@ def _handshake(self):
if info == dh_key_info_1 or info == dh_key_info_2 or info == dh_key_info_3:
raise_dh_params()

if libcrypto_version_info < (1, 1):
if error_code_version_info < (1, 1):
unknown_protocol_info = (
LibsslConst.ERR_LIB_SSL,
LibsslConst.SSL_F_SSL23_GET_SERVER_HELLO,
Expand All @@ -580,23 +580,16 @@ def _handshake(self):
if info == tls_version_info_error:
raise_protocol_version()

# There are multiple functions that can result in a handshake failure,
# but our custom handshake parsing code figures out what really happened,
# and what is more, OpenSSL 3 got rid of function codes. Because of this,
# we skip checking the function code.
handshake_error_info = (
LibsslConst.ERR_LIB_SSL,
LibsslConst.SSL_F_SSL23_GET_SERVER_HELLO,
LibsslConst.SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE
)
# OpenSSL 3.0 no longer has func codes, so this can be confused
# with the following handler which needs to check for client auth
if libcrypto_version_info < (3, ) and info == handshake_error_info:
raise_handshake()

handshake_failure_info = (
LibsslConst.ERR_LIB_SSL,
LibsslConst.SSL_F_SSL3_READ_BYTES,
LibsslConst.SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE
)
handshake_failure_info = _homogenize_openssl3_error(handshake_failure_info)
if info == handshake_failure_info:
if (info[0], info[2]) == handshake_error_info:
saw_client_auth = False
for record_type, _, record_data in parse_tls_records(handshake_server_bytes):
if record_type != b'\x16':
Expand All @@ -609,7 +602,7 @@ def _handshake(self):
raise_client_auth()
raise_handshake()

if libcrypto_version_info < (1, 1):
if error_code_version_info < (1, 1):
cert_verify_failed_info = (
LibsslConst.ERR_LIB_SSL,
LibsslConst.SSL_F_SSL3_GET_SERVER_CERTIFICATE,
Expand Down

0 comments on commit 085c63f

Please sign in to comment.