update Linux_x86_64
This commit is contained in:
parent
93422b0274
commit
e7ebbedd38
336 changed files with 34353 additions and 21020 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -3,3 +3,4 @@
|
||||||
*.pyo
|
*.pyo
|
||||||
*.pyd
|
*.pyd
|
||||||
__pycache__
|
__pycache__
|
||||||
|
pip_cache
|
||||||
|
|
|
@ -1,29 +1,39 @@
|
||||||
from sys import platform
|
from sys import platform
|
||||||
from functools import wraps, partial
|
from functools import wraps, partial
|
||||||
from itertools import count
|
from itertools import count, chain
|
||||||
from weakref import WeakValueDictionary
|
from weakref import WeakValueDictionary
|
||||||
from errno import errorcode
|
from errno import errorcode
|
||||||
|
|
||||||
from six import text_type as _text_type
|
from six import text_type as _text_type
|
||||||
|
from six import binary_type as _binary_type
|
||||||
from six import integer_types as integer_types
|
from six import integer_types as integer_types
|
||||||
|
from six import int2byte, indexbytes
|
||||||
|
|
||||||
from OpenSSL._util import (
|
from OpenSSL._util import (
|
||||||
ffi as _ffi,
|
ffi as _ffi,
|
||||||
lib as _lib,
|
lib as _lib,
|
||||||
exception_from_error_queue as _exception_from_error_queue,
|
exception_from_error_queue as _exception_from_error_queue,
|
||||||
native as _native)
|
native as _native,
|
||||||
|
text_to_bytes_and_warn as _text_to_bytes_and_warn,
|
||||||
|
path_string as _path_string,
|
||||||
|
UNSPECIFIED as _UNSPECIFIED,
|
||||||
|
)
|
||||||
|
|
||||||
from OpenSSL.crypto import (
|
from OpenSSL.crypto import (
|
||||||
FILETYPE_PEM, _PassphraseHelper, PKey, X509Name, X509, X509Store)
|
FILETYPE_PEM, _PassphraseHelper, PKey, X509Name, X509, X509Store)
|
||||||
|
|
||||||
_unspecified = object()
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
_memoryview = memoryview
|
_memoryview = memoryview
|
||||||
except NameError:
|
except NameError:
|
||||||
class _memoryview(object):
|
class _memoryview(object):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
_buffer = buffer
|
||||||
|
except NameError:
|
||||||
|
class _buffer(object):
|
||||||
|
pass
|
||||||
|
|
||||||
OPENSSL_VERSION_NUMBER = _lib.OPENSSL_VERSION_NUMBER
|
OPENSSL_VERSION_NUMBER = _lib.OPENSSL_VERSION_NUMBER
|
||||||
SSLEAY_VERSION = _lib.SSLEAY_VERSION
|
SSLEAY_VERSION = _lib.SSLEAY_VERSION
|
||||||
SSLEAY_CFLAGS = _lib.SSLEAY_CFLAGS
|
SSLEAY_CFLAGS = _lib.SSLEAY_CFLAGS
|
||||||
|
@ -81,7 +91,10 @@ except AttributeError:
|
||||||
|
|
||||||
OP_NO_QUERY_MTU = _lib.SSL_OP_NO_QUERY_MTU
|
OP_NO_QUERY_MTU = _lib.SSL_OP_NO_QUERY_MTU
|
||||||
OP_COOKIE_EXCHANGE = _lib.SSL_OP_COOKIE_EXCHANGE
|
OP_COOKIE_EXCHANGE = _lib.SSL_OP_COOKIE_EXCHANGE
|
||||||
OP_NO_TICKET = _lib.SSL_OP_NO_TICKET
|
try:
|
||||||
|
OP_NO_TICKET = _lib.SSL_OP_NO_TICKET
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
|
||||||
OP_ALL = _lib.SSL_OP_ALL
|
OP_ALL = _lib.SSL_OP_ALL
|
||||||
|
|
||||||
|
@ -121,7 +134,6 @@ SSL_CB_CONNECT_EXIT = _lib.SSL_CB_CONNECT_EXIT
|
||||||
SSL_CB_HANDSHAKE_START = _lib.SSL_CB_HANDSHAKE_START
|
SSL_CB_HANDSHAKE_START = _lib.SSL_CB_HANDSHAKE_START
|
||||||
SSL_CB_HANDSHAKE_DONE = _lib.SSL_CB_HANDSHAKE_DONE
|
SSL_CB_HANDSHAKE_DONE = _lib.SSL_CB_HANDSHAKE_DONE
|
||||||
|
|
||||||
|
|
||||||
class Error(Exception):
|
class Error(Exception):
|
||||||
"""
|
"""
|
||||||
An error occurred in an `OpenSSL.SSL` API.
|
An error occurred in an `OpenSSL.SSL` API.
|
||||||
|
@ -156,11 +168,42 @@ class SysCallError(Error):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class _CallbackExceptionHelper(object):
|
||||||
|
"""
|
||||||
|
A base class for wrapper classes that allow for intelligent exception
|
||||||
|
handling in OpenSSL callbacks.
|
||||||
|
|
||||||
class _VerifyHelper(object):
|
:ivar list _problems: Any exceptions that occurred while executing in a
|
||||||
def __init__(self, connection, callback):
|
context where they could not be raised in the normal way. Typically
|
||||||
|
this is because OpenSSL has called into some Python code and requires a
|
||||||
|
return value. The exceptions are saved to be raised later when it is
|
||||||
|
possible to do so.
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
self._problems = []
|
self._problems = []
|
||||||
|
|
||||||
|
|
||||||
|
def raise_if_problem(self):
|
||||||
|
"""
|
||||||
|
Raise an exception from the OpenSSL error queue or that was previously
|
||||||
|
captured whe running a callback.
|
||||||
|
"""
|
||||||
|
if self._problems:
|
||||||
|
try:
|
||||||
|
_raise_current_error()
|
||||||
|
except Error:
|
||||||
|
pass
|
||||||
|
raise self._problems.pop(0)
|
||||||
|
|
||||||
|
|
||||||
|
class _VerifyHelper(_CallbackExceptionHelper):
|
||||||
|
"""
|
||||||
|
Wrap a callback such that it can be used as a certificate verification
|
||||||
|
callback.
|
||||||
|
"""
|
||||||
|
def __init__(self, callback):
|
||||||
|
_CallbackExceptionHelper.__init__(self)
|
||||||
|
|
||||||
@wraps(callback)
|
@wraps(callback)
|
||||||
def wrapper(ok, store_ctx):
|
def wrapper(ok, store_ctx):
|
||||||
cert = X509.__new__(X509)
|
cert = X509.__new__(X509)
|
||||||
|
@ -168,6 +211,10 @@ class _VerifyHelper(object):
|
||||||
error_number = _lib.X509_STORE_CTX_get_error(store_ctx)
|
error_number = _lib.X509_STORE_CTX_get_error(store_ctx)
|
||||||
error_depth = _lib.X509_STORE_CTX_get_error_depth(store_ctx)
|
error_depth = _lib.X509_STORE_CTX_get_error_depth(store_ctx)
|
||||||
|
|
||||||
|
index = _lib.SSL_get_ex_data_X509_STORE_CTX_idx()
|
||||||
|
ssl = _lib.X509_STORE_CTX_get_ex_data(store_ctx, index)
|
||||||
|
connection = Connection._reverse_mapping[ssl]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
result = callback(connection, cert, error_number, error_depth, ok)
|
result = callback(connection, cert, error_number, error_depth, ok)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
@ -184,14 +231,142 @@ class _VerifyHelper(object):
|
||||||
"int (*)(int, X509_STORE_CTX *)", wrapper)
|
"int (*)(int, X509_STORE_CTX *)", wrapper)
|
||||||
|
|
||||||
|
|
||||||
def raise_if_problem(self):
|
class _NpnAdvertiseHelper(_CallbackExceptionHelper):
|
||||||
if self._problems:
|
"""
|
||||||
try:
|
Wrap a callback such that it can be used as an NPN advertisement callback.
|
||||||
_raise_current_error()
|
"""
|
||||||
except Error:
|
def __init__(self, callback):
|
||||||
pass
|
_CallbackExceptionHelper.__init__(self)
|
||||||
raise self._problems.pop(0)
|
|
||||||
|
|
||||||
|
@wraps(callback)
|
||||||
|
def wrapper(ssl, out, outlen, arg):
|
||||||
|
try:
|
||||||
|
conn = Connection._reverse_mapping[ssl]
|
||||||
|
protos = callback(conn)
|
||||||
|
|
||||||
|
# Join the protocols into a Python bytestring, length-prefixing
|
||||||
|
# each element.
|
||||||
|
protostr = b''.join(
|
||||||
|
chain.from_iterable((int2byte(len(p)), p) for p in protos)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Save our callback arguments on the connection object. This is
|
||||||
|
# done to make sure that they don't get freed before OpenSSL
|
||||||
|
# uses them. Then, return them appropriately in the output
|
||||||
|
# parameters.
|
||||||
|
conn._npn_advertise_callback_args = [
|
||||||
|
_ffi.new("unsigned int *", len(protostr)),
|
||||||
|
_ffi.new("unsigned char[]", protostr),
|
||||||
|
]
|
||||||
|
outlen[0] = conn._npn_advertise_callback_args[0][0]
|
||||||
|
out[0] = conn._npn_advertise_callback_args[1]
|
||||||
|
return 0
|
||||||
|
except Exception as e:
|
||||||
|
self._problems.append(e)
|
||||||
|
return 2 # SSL_TLSEXT_ERR_ALERT_FATAL
|
||||||
|
|
||||||
|
self.callback = _ffi.callback(
|
||||||
|
"int (*)(SSL *, const unsigned char **, unsigned int *, void *)",
|
||||||
|
wrapper
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class _NpnSelectHelper(_CallbackExceptionHelper):
|
||||||
|
"""
|
||||||
|
Wrap a callback such that it can be used as an NPN selection callback.
|
||||||
|
"""
|
||||||
|
def __init__(self, callback):
|
||||||
|
_CallbackExceptionHelper.__init__(self)
|
||||||
|
|
||||||
|
@wraps(callback)
|
||||||
|
def wrapper(ssl, out, outlen, in_, inlen, arg):
|
||||||
|
try:
|
||||||
|
conn = Connection._reverse_mapping[ssl]
|
||||||
|
|
||||||
|
# The string passed to us is actually made up of multiple
|
||||||
|
# length-prefixed bytestrings. We need to split that into a
|
||||||
|
# list.
|
||||||
|
instr = _ffi.buffer(in_, inlen)[:]
|
||||||
|
protolist = []
|
||||||
|
while instr:
|
||||||
|
l = indexbytes(instr, 0)
|
||||||
|
proto = instr[1:l+1]
|
||||||
|
protolist.append(proto)
|
||||||
|
instr = instr[l+1:]
|
||||||
|
|
||||||
|
# Call the callback
|
||||||
|
outstr = callback(conn, protolist)
|
||||||
|
|
||||||
|
# Save our callback arguments on the connection object. This is
|
||||||
|
# done to make sure that they don't get freed before OpenSSL
|
||||||
|
# uses them. Then, return them appropriately in the output
|
||||||
|
# parameters.
|
||||||
|
conn._npn_select_callback_args = [
|
||||||
|
_ffi.new("unsigned char *", len(outstr)),
|
||||||
|
_ffi.new("unsigned char[]", outstr),
|
||||||
|
]
|
||||||
|
outlen[0] = conn._npn_select_callback_args[0][0]
|
||||||
|
out[0] = conn._npn_select_callback_args[1]
|
||||||
|
return 0
|
||||||
|
except Exception as e:
|
||||||
|
self._problems.append(e)
|
||||||
|
return 2 # SSL_TLSEXT_ERR_ALERT_FATAL
|
||||||
|
|
||||||
|
self.callback = _ffi.callback(
|
||||||
|
"int (*)(SSL *, unsigned char **, unsigned char *, "
|
||||||
|
"const unsigned char *, unsigned int, void *)",
|
||||||
|
wrapper
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class _ALPNSelectHelper(_CallbackExceptionHelper):
|
||||||
|
"""
|
||||||
|
Wrap a callback such that it can be used as an ALPN selection callback.
|
||||||
|
"""
|
||||||
|
def __init__(self, callback):
|
||||||
|
_CallbackExceptionHelper.__init__(self)
|
||||||
|
|
||||||
|
@wraps(callback)
|
||||||
|
def wrapper(ssl, out, outlen, in_, inlen, arg):
|
||||||
|
try:
|
||||||
|
conn = Connection._reverse_mapping[ssl]
|
||||||
|
|
||||||
|
# The string passed to us is made up of multiple
|
||||||
|
# length-prefixed bytestrings. We need to split that into a
|
||||||
|
# list.
|
||||||
|
instr = _ffi.buffer(in_, inlen)[:]
|
||||||
|
protolist = []
|
||||||
|
while instr:
|
||||||
|
encoded_len = indexbytes(instr, 0)
|
||||||
|
proto = instr[1:encoded_len + 1]
|
||||||
|
protolist.append(proto)
|
||||||
|
instr = instr[encoded_len + 1:]
|
||||||
|
|
||||||
|
# Call the callback
|
||||||
|
outstr = callback(conn, protolist)
|
||||||
|
|
||||||
|
if not isinstance(outstr, _binary_type):
|
||||||
|
raise TypeError("ALPN callback must return a bytestring.")
|
||||||
|
|
||||||
|
# Save our callback arguments on the connection object to make
|
||||||
|
# sure that they don't get freed before OpenSSL can use them.
|
||||||
|
# Then, return them in the appropriate output parameters.
|
||||||
|
conn._alpn_select_callback_args = [
|
||||||
|
_ffi.new("unsigned char *", len(outstr)),
|
||||||
|
_ffi.new("unsigned char[]", outstr),
|
||||||
|
]
|
||||||
|
outlen[0] = conn._alpn_select_callback_args[0][0]
|
||||||
|
out[0] = conn._alpn_select_callback_args[1]
|
||||||
|
return 0
|
||||||
|
except Exception as e:
|
||||||
|
self._problems.append(e)
|
||||||
|
return 2 # SSL_TLSEXT_ERR_ALERT_FATAL
|
||||||
|
|
||||||
|
self.callback = _ffi.callback(
|
||||||
|
"int (*)(SSL *, unsigned char **, unsigned char *, "
|
||||||
|
"const unsigned char *, unsigned int, void *)",
|
||||||
|
wrapper
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def _asFileDescriptor(obj):
|
def _asFileDescriptor(obj):
|
||||||
|
@ -223,6 +398,37 @@ def SSLeay_version(type):
|
||||||
return _ffi.string(_lib.SSLeay_version(type))
|
return _ffi.string(_lib.SSLeay_version(type))
|
||||||
|
|
||||||
|
|
||||||
|
def _requires_npn(func):
|
||||||
|
"""
|
||||||
|
Wraps any function that requires NPN support in OpenSSL, ensuring that
|
||||||
|
NotImplementedError is raised if NPN is not present.
|
||||||
|
"""
|
||||||
|
@wraps(func)
|
||||||
|
def wrapper(*args, **kwargs):
|
||||||
|
if not _lib.Cryptography_HAS_NEXTPROTONEG:
|
||||||
|
raise NotImplementedError("NPN not available.")
|
||||||
|
|
||||||
|
return func(*args, **kwargs)
|
||||||
|
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def _requires_alpn(func):
|
||||||
|
"""
|
||||||
|
Wraps any function that requires ALPN support in OpenSSL, ensuring that
|
||||||
|
NotImplementedError is raised if ALPN support is not present.
|
||||||
|
"""
|
||||||
|
@wraps(func)
|
||||||
|
def wrapper(*args, **kwargs):
|
||||||
|
if not _lib.Cryptography_HAS_ALPN:
|
||||||
|
raise NotImplementedError("ALPN not available.")
|
||||||
|
|
||||||
|
return func(*args, **kwargs)
|
||||||
|
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Session(object):
|
class Session(object):
|
||||||
pass
|
pass
|
||||||
|
@ -235,6 +441,7 @@ class Context(object):
|
||||||
new SSL connections.
|
new SSL connections.
|
||||||
"""
|
"""
|
||||||
_methods = {
|
_methods = {
|
||||||
|
SSLv2_METHOD: "SSLv2_method",
|
||||||
SSLv3_METHOD: "SSLv3_method",
|
SSLv3_METHOD: "SSLv3_method",
|
||||||
SSLv23_METHOD: "SSLv23_method",
|
SSLv23_METHOD: "SSLv23_method",
|
||||||
TLSv1_METHOD: "TLSv1_method",
|
TLSv1_METHOD: "TLSv1_method",
|
||||||
|
@ -280,6 +487,12 @@ class Context(object):
|
||||||
self._info_callback = None
|
self._info_callback = None
|
||||||
self._tlsext_servername_callback = None
|
self._tlsext_servername_callback = None
|
||||||
self._app_data = None
|
self._app_data = None
|
||||||
|
self._npn_advertise_helper = None
|
||||||
|
self._npn_advertise_callback = None
|
||||||
|
self._npn_select_helper = None
|
||||||
|
self._npn_select_callback = None
|
||||||
|
self._alpn_select_helper = None
|
||||||
|
self._alpn_select_callback = None
|
||||||
|
|
||||||
# SSL_CTX_set_app_data(self->ctx, self);
|
# SSL_CTX_set_app_data(self->ctx, self);
|
||||||
# SSL_CTX_set_mode(self->ctx, SSL_MODE_ENABLE_PARTIAL_WRITE |
|
# SSL_CTX_set_mode(self->ctx, SSL_MODE_ENABLE_PARTIAL_WRITE |
|
||||||
|
@ -293,19 +506,22 @@ class Context(object):
|
||||||
Let SSL know where we can find trusted certificates for the certificate
|
Let SSL know where we can find trusted certificates for the certificate
|
||||||
chain
|
chain
|
||||||
|
|
||||||
:param cafile: In which file we can find the certificates
|
:param cafile: In which file we can find the certificates (``bytes`` or
|
||||||
|
``unicode``).
|
||||||
:param capath: In which directory we can find the certificates
|
:param capath: In which directory we can find the certificates
|
||||||
|
(``bytes`` or ``unicode``).
|
||||||
|
|
||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
if cafile is None:
|
if cafile is None:
|
||||||
cafile = _ffi.NULL
|
cafile = _ffi.NULL
|
||||||
elif not isinstance(cafile, bytes):
|
else:
|
||||||
raise TypeError("cafile must be None or a byte string")
|
cafile = _path_string(cafile)
|
||||||
|
|
||||||
if capath is None:
|
if capath is None:
|
||||||
capath = _ffi.NULL
|
capath = _ffi.NULL
|
||||||
elif not isinstance(capath, bytes):
|
else:
|
||||||
raise TypeError("capath must be None or a byte string")
|
capath = _path_string(capath)
|
||||||
|
|
||||||
load_result = _lib.SSL_CTX_load_verify_locations(self._context, cafile, capath)
|
load_result = _lib.SSL_CTX_load_verify_locations(self._context, cafile, capath)
|
||||||
if not load_result:
|
if not load_result:
|
||||||
|
@ -355,15 +571,12 @@ class Context(object):
|
||||||
"""
|
"""
|
||||||
Load a certificate chain from a file
|
Load a certificate chain from a file
|
||||||
|
|
||||||
:param certfile: The name of the certificate chain file
|
:param certfile: The name of the certificate chain file (``bytes`` or
|
||||||
|
``unicode``).
|
||||||
|
|
||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
if isinstance(certfile, _text_type):
|
certfile = _path_string(certfile)
|
||||||
# Perhaps sys.getfilesystemencoding() could be better?
|
|
||||||
certfile = certfile.encode("utf-8")
|
|
||||||
|
|
||||||
if not isinstance(certfile, bytes):
|
|
||||||
raise TypeError("certfile must be bytes or unicode")
|
|
||||||
|
|
||||||
result = _lib.SSL_CTX_use_certificate_chain_file(self._context, certfile)
|
result = _lib.SSL_CTX_use_certificate_chain_file(self._context, certfile)
|
||||||
if not result:
|
if not result:
|
||||||
|
@ -374,15 +587,13 @@ class Context(object):
|
||||||
"""
|
"""
|
||||||
Load a certificate from a file
|
Load a certificate from a file
|
||||||
|
|
||||||
:param certfile: The name of the certificate file
|
:param certfile: The name of the certificate file (``bytes`` or
|
||||||
|
``unicode``).
|
||||||
:param filetype: (optional) The encoding of the file, default is PEM
|
:param filetype: (optional) The encoding of the file, default is PEM
|
||||||
|
|
||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
if isinstance(certfile, _text_type):
|
certfile = _path_string(certfile)
|
||||||
# Perhaps sys.getfilesystemencoding() could be better?
|
|
||||||
certfile = certfile.encode("utf-8")
|
|
||||||
if not isinstance(certfile, bytes):
|
|
||||||
raise TypeError("certfile must be bytes or unicode")
|
|
||||||
if not isinstance(filetype, integer_types):
|
if not isinstance(filetype, integer_types):
|
||||||
raise TypeError("filetype must be an integer")
|
raise TypeError("filetype must be an integer")
|
||||||
|
|
||||||
|
@ -432,22 +643,18 @@ class Context(object):
|
||||||
raise exception
|
raise exception
|
||||||
|
|
||||||
|
|
||||||
def use_privatekey_file(self, keyfile, filetype=_unspecified):
|
def use_privatekey_file(self, keyfile, filetype=_UNSPECIFIED):
|
||||||
"""
|
"""
|
||||||
Load a private key from a file
|
Load a private key from a file
|
||||||
|
|
||||||
:param keyfile: The name of the key file
|
:param keyfile: The name of the key file (``bytes`` or ``unicode``)
|
||||||
:param filetype: (optional) The encoding of the file, default is PEM
|
:param filetype: (optional) The encoding of the file, default is PEM
|
||||||
|
|
||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
if isinstance(keyfile, _text_type):
|
keyfile = _path_string(keyfile)
|
||||||
# Perhaps sys.getfilesystemencoding() could be better?
|
|
||||||
keyfile = keyfile.encode("utf-8")
|
|
||||||
|
|
||||||
if not isinstance(keyfile, bytes):
|
if filetype is _UNSPECIFIED:
|
||||||
raise TypeError("keyfile must be a byte string")
|
|
||||||
|
|
||||||
if filetype is _unspecified:
|
|
||||||
filetype = FILETYPE_PEM
|
filetype = FILETYPE_PEM
|
||||||
elif not isinstance(filetype, integer_types):
|
elif not isinstance(filetype, integer_types):
|
||||||
raise TypeError("filetype must be an integer")
|
raise TypeError("filetype must be an integer")
|
||||||
|
@ -479,6 +686,9 @@ class Context(object):
|
||||||
|
|
||||||
:return: None (raises an exception if something's wrong)
|
:return: None (raises an exception if something's wrong)
|
||||||
"""
|
"""
|
||||||
|
if not _lib.SSL_CTX_check_private_key(self._context):
|
||||||
|
_raise_current_error()
|
||||||
|
|
||||||
|
|
||||||
def load_client_ca(self, cafile):
|
def load_client_ca(self, cafile):
|
||||||
"""
|
"""
|
||||||
|
@ -538,7 +748,7 @@ class Context(object):
|
||||||
if not callable(callback):
|
if not callable(callback):
|
||||||
raise TypeError("callback must be callable")
|
raise TypeError("callback must be callable")
|
||||||
|
|
||||||
self._verify_helper = _VerifyHelper(self, callback)
|
self._verify_helper = _VerifyHelper(callback)
|
||||||
self._verify_callback = self._verify_helper.callback
|
self._verify_callback = self._verify_helper.callback
|
||||||
_lib.SSL_CTX_set_verify(self._context, mode, self._verify_callback)
|
_lib.SSL_CTX_set_verify(self._context, mode, self._verify_callback)
|
||||||
|
|
||||||
|
@ -578,11 +788,12 @@ class Context(object):
|
||||||
"""
|
"""
|
||||||
Load parameters for Ephemeral Diffie-Hellman
|
Load parameters for Ephemeral Diffie-Hellman
|
||||||
|
|
||||||
:param dhfile: The file to load EDH parameters from
|
:param dhfile: The file to load EDH parameters from (``bytes`` or
|
||||||
|
``unicode``).
|
||||||
|
|
||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
if not isinstance(dhfile, bytes):
|
dhfile = _path_string(dhfile)
|
||||||
raise TypeError("dhfile must be a byte string")
|
|
||||||
|
|
||||||
bio = _lib.BIO_new_file(dhfile, b"r")
|
bio = _lib.BIO_new_file(dhfile, b"r")
|
||||||
if bio == _ffi.NULL:
|
if bio == _ffi.NULL:
|
||||||
|
@ -594,6 +805,19 @@ class Context(object):
|
||||||
_lib.SSL_CTX_set_tmp_dh(self._context, dh)
|
_lib.SSL_CTX_set_tmp_dh(self._context, dh)
|
||||||
|
|
||||||
|
|
||||||
|
def set_tmp_ecdh(self, curve):
|
||||||
|
"""
|
||||||
|
Select a curve to use for ECDHE key exchange.
|
||||||
|
|
||||||
|
:param curve: A curve object to use as returned by either
|
||||||
|
:py:meth:`OpenSSL.crypto.get_elliptic_curve` or
|
||||||
|
:py:meth:`OpenSSL.crypto.get_elliptic_curves`.
|
||||||
|
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
_lib.SSL_CTX_set_tmp_ecdh(self._context, curve._to_EC_KEY())
|
||||||
|
|
||||||
|
|
||||||
def set_cipher_list(self, cipher_list):
|
def set_cipher_list(self, cipher_list):
|
||||||
"""
|
"""
|
||||||
Change the cipher list
|
Change the cipher list
|
||||||
|
@ -783,6 +1007,79 @@ class Context(object):
|
||||||
_lib.SSL_CTX_set_tlsext_servername_callback(
|
_lib.SSL_CTX_set_tlsext_servername_callback(
|
||||||
self._context, self._tlsext_servername_callback)
|
self._context, self._tlsext_servername_callback)
|
||||||
|
|
||||||
|
|
||||||
|
@_requires_npn
|
||||||
|
def set_npn_advertise_callback(self, callback):
|
||||||
|
"""
|
||||||
|
Specify a callback function that will be called when offering `Next
|
||||||
|
Protocol Negotiation
|
||||||
|
<https://technotes.googlecode.com/git/nextprotoneg.html>`_ as a server.
|
||||||
|
|
||||||
|
:param callback: The callback function. It will be invoked with one
|
||||||
|
argument, the Connection instance. It should return a list of
|
||||||
|
bytestrings representing the advertised protocols, like
|
||||||
|
``[b'http/1.1', b'spdy/2']``.
|
||||||
|
"""
|
||||||
|
self._npn_advertise_helper = _NpnAdvertiseHelper(callback)
|
||||||
|
self._npn_advertise_callback = self._npn_advertise_helper.callback
|
||||||
|
_lib.SSL_CTX_set_next_protos_advertised_cb(
|
||||||
|
self._context, self._npn_advertise_callback, _ffi.NULL)
|
||||||
|
|
||||||
|
|
||||||
|
@_requires_npn
|
||||||
|
def set_npn_select_callback(self, callback):
|
||||||
|
"""
|
||||||
|
Specify a callback function that will be called when a server offers
|
||||||
|
Next Protocol Negotiation options.
|
||||||
|
|
||||||
|
:param callback: The callback function. It will be invoked with two
|
||||||
|
arguments: the Connection, and a list of offered protocols as
|
||||||
|
bytestrings, e.g. ``[b'http/1.1', b'spdy/2']``. It should return
|
||||||
|
one of those bytestrings, the chosen protocol.
|
||||||
|
"""
|
||||||
|
self._npn_select_helper = _NpnSelectHelper(callback)
|
||||||
|
self._npn_select_callback = self._npn_select_helper.callback
|
||||||
|
_lib.SSL_CTX_set_next_proto_select_cb(
|
||||||
|
self._context, self._npn_select_callback, _ffi.NULL)
|
||||||
|
|
||||||
|
@_requires_alpn
|
||||||
|
def set_alpn_protos(self, protos):
|
||||||
|
"""
|
||||||
|
Specify the clients ALPN protocol list.
|
||||||
|
|
||||||
|
These protocols are offered to the server during protocol negotiation.
|
||||||
|
|
||||||
|
:param protos: A list of the protocols to be offered to the server.
|
||||||
|
This list should be a Python list of bytestrings representing the
|
||||||
|
protocols to offer, e.g. ``[b'http/1.1', b'spdy/2']``.
|
||||||
|
"""
|
||||||
|
# Take the list of protocols and join them together, prefixing them
|
||||||
|
# with their lengths.
|
||||||
|
protostr = b''.join(
|
||||||
|
chain.from_iterable((int2byte(len(p)), p) for p in protos)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Build a C string from the list. We don't need to save this off
|
||||||
|
# because OpenSSL immediately copies the data out.
|
||||||
|
input_str = _ffi.new("unsigned char[]", protostr)
|
||||||
|
input_str_len = _ffi.cast("unsigned", len(protostr))
|
||||||
|
_lib.SSL_CTX_set_alpn_protos(self._context, input_str, input_str_len)
|
||||||
|
|
||||||
|
@_requires_alpn
|
||||||
|
def set_alpn_select_callback(self, callback):
|
||||||
|
"""
|
||||||
|
Set the callback to handle ALPN protocol choice.
|
||||||
|
|
||||||
|
:param callback: The callback function. It will be invoked with two
|
||||||
|
arguments: the Connection, and a list of offered protocols as
|
||||||
|
bytestrings, e.g ``[b'http/1.1', b'spdy/2']``. It should return
|
||||||
|
one of those bytestrings, the chosen protocol.
|
||||||
|
"""
|
||||||
|
self._alpn_select_helper = _ALPNSelectHelper(callback)
|
||||||
|
self._alpn_select_callback = self._alpn_select_helper.callback
|
||||||
|
_lib.SSL_CTX_set_alpn_select_cb(
|
||||||
|
self._context, self._alpn_select_callback, _ffi.NULL)
|
||||||
|
|
||||||
ContextType = Context
|
ContextType = Context
|
||||||
|
|
||||||
|
|
||||||
|
@ -807,6 +1104,19 @@ class Connection(object):
|
||||||
self._ssl = _ffi.gc(ssl, _lib.SSL_free)
|
self._ssl = _ffi.gc(ssl, _lib.SSL_free)
|
||||||
self._context = context
|
self._context = context
|
||||||
|
|
||||||
|
# References to strings used for Next Protocol Negotiation. OpenSSL's
|
||||||
|
# header files suggest that these might get copied at some point, but
|
||||||
|
# doesn't specify when, so we store them here to make sure they don't
|
||||||
|
# get freed before OpenSSL uses them.
|
||||||
|
self._npn_advertise_callback_args = None
|
||||||
|
self._npn_select_callback_args = None
|
||||||
|
|
||||||
|
# References to strings used for Application Layer Protocol
|
||||||
|
# Negotiation. These strings get copied at some point but it's well
|
||||||
|
# after the callback returns, so we have to hang them somewhere to
|
||||||
|
# avoid them getting freed.
|
||||||
|
self._alpn_select_callback_args = None
|
||||||
|
|
||||||
self._reverse_mapping[self._ssl] = self
|
self._reverse_mapping[self._ssl] = self
|
||||||
|
|
||||||
if socket is None:
|
if socket is None:
|
||||||
|
@ -841,6 +1151,12 @@ class Connection(object):
|
||||||
def _raise_ssl_error(self, ssl, result):
|
def _raise_ssl_error(self, ssl, result):
|
||||||
if self._context._verify_helper is not None:
|
if self._context._verify_helper is not None:
|
||||||
self._context._verify_helper.raise_if_problem()
|
self._context._verify_helper.raise_if_problem()
|
||||||
|
if self._context._npn_advertise_helper is not None:
|
||||||
|
self._context._npn_advertise_helper.raise_if_problem()
|
||||||
|
if self._context._npn_select_helper is not None:
|
||||||
|
self._context._npn_select_helper.raise_if_problem()
|
||||||
|
if self._context._alpn_select_helper is not None:
|
||||||
|
self._context._alpn_select_helper.raise_if_problem()
|
||||||
|
|
||||||
error = _lib.SSL_get_error(ssl, result)
|
error = _lib.SSL_get_error(ssl, result)
|
||||||
if error == _lib.SSL_ERROR_WANT_READ:
|
if error == _lib.SSL_ERROR_WANT_READ:
|
||||||
|
@ -859,7 +1175,7 @@ class Connection(object):
|
||||||
errno = _ffi.getwinerror()[0]
|
errno = _ffi.getwinerror()[0]
|
||||||
else:
|
else:
|
||||||
errno = _ffi.errno
|
errno = _ffi.errno
|
||||||
raise SysCallError(errno, errorcode[errno])
|
raise SysCallError(errno, errorcode.get(errno))
|
||||||
else:
|
else:
|
||||||
raise SysCallError(-1, "Unexpected EOF")
|
raise SysCallError(-1, "Unexpected EOF")
|
||||||
else:
|
else:
|
||||||
|
@ -936,15 +1252,20 @@ class Connection(object):
|
||||||
WantWrite or WantX509Lookup exceptions on this, you have to call the
|
WantWrite or WantX509Lookup exceptions on this, you have to call the
|
||||||
method again with the SAME buffer.
|
method again with the SAME buffer.
|
||||||
|
|
||||||
:param buf: The string to send
|
:param buf: The string, buffer or memoryview to send
|
||||||
:param flags: (optional) Included for compatibility with the socket
|
:param flags: (optional) Included for compatibility with the socket
|
||||||
API, the value is ignored
|
API, the value is ignored
|
||||||
:return: The number of bytes written
|
:return: The number of bytes written
|
||||||
"""
|
"""
|
||||||
|
# Backward compatibility
|
||||||
|
buf = _text_to_bytes_and_warn("buf", buf)
|
||||||
|
|
||||||
if isinstance(buf, _memoryview):
|
if isinstance(buf, _memoryview):
|
||||||
buf = buf.tobytes()
|
buf = buf.tobytes()
|
||||||
|
if isinstance(buf, _buffer):
|
||||||
|
buf = str(buf)
|
||||||
if not isinstance(buf, bytes):
|
if not isinstance(buf, bytes):
|
||||||
raise TypeError("data must be a byte string")
|
raise TypeError("data must be a memoryview, buffer or byte string")
|
||||||
|
|
||||||
result = _lib.SSL_write(self._ssl, buf, len(buf))
|
result = _lib.SSL_write(self._ssl, buf, len(buf))
|
||||||
self._raise_ssl_error(self._ssl, result)
|
self._raise_ssl_error(self._ssl, result)
|
||||||
|
@ -958,15 +1279,19 @@ class Connection(object):
|
||||||
all data is sent. If an error occurs, it's impossible to tell how much
|
all data is sent. If an error occurs, it's impossible to tell how much
|
||||||
data has been sent.
|
data has been sent.
|
||||||
|
|
||||||
:param buf: The string to send
|
:param buf: The string, buffer or memoryview to send
|
||||||
:param flags: (optional) Included for compatibility with the socket
|
:param flags: (optional) Included for compatibility with the socket
|
||||||
API, the value is ignored
|
API, the value is ignored
|
||||||
:return: The number of bytes written
|
:return: The number of bytes written
|
||||||
"""
|
"""
|
||||||
|
buf = _text_to_bytes_and_warn("buf", buf)
|
||||||
|
|
||||||
if isinstance(buf, _memoryview):
|
if isinstance(buf, _memoryview):
|
||||||
buf = buf.tobytes()
|
buf = buf.tobytes()
|
||||||
|
if isinstance(buf, _buffer):
|
||||||
|
buf = str(buf)
|
||||||
if not isinstance(buf, bytes):
|
if not isinstance(buf, bytes):
|
||||||
raise TypeError("buf must be a byte string")
|
raise TypeError("buf must be a memoryview, buffer or byte string")
|
||||||
|
|
||||||
left_to_send = len(buf)
|
left_to_send = len(buf)
|
||||||
total_sent = 0
|
total_sent = 0
|
||||||
|
@ -997,6 +1322,45 @@ class Connection(object):
|
||||||
read = recv
|
read = recv
|
||||||
|
|
||||||
|
|
||||||
|
def recv_into(self, buffer, nbytes=None, flags=None):
|
||||||
|
"""
|
||||||
|
Receive data on the connection and store the data into a buffer rather
|
||||||
|
than creating a new string.
|
||||||
|
|
||||||
|
:param buffer: The buffer to copy into.
|
||||||
|
:param nbytes: (optional) The maximum number of bytes to read into the
|
||||||
|
buffer. If not present, defaults to the size of the buffer. If
|
||||||
|
larger than the size of the buffer, is reduced to the size of the
|
||||||
|
buffer.
|
||||||
|
:param flags: (optional) Included for compatibility with the socket
|
||||||
|
API, the value is ignored.
|
||||||
|
:return: The number of bytes read into the buffer.
|
||||||
|
"""
|
||||||
|
if nbytes is None:
|
||||||
|
nbytes = len(buffer)
|
||||||
|
else:
|
||||||
|
nbytes = min(nbytes, len(buffer))
|
||||||
|
|
||||||
|
# We need to create a temporary buffer. This is annoying, it would be
|
||||||
|
# better if we could pass memoryviews straight into the SSL_read call,
|
||||||
|
# but right now we can't. Revisit this if CFFI gets that ability.
|
||||||
|
buf = _ffi.new("char[]", nbytes)
|
||||||
|
result = _lib.SSL_read(self._ssl, buf, nbytes)
|
||||||
|
self._raise_ssl_error(self._ssl, result)
|
||||||
|
|
||||||
|
# This strange line is all to avoid a memory copy. The buffer protocol
|
||||||
|
# should allow us to assign a CFFI buffer to the LHS of this line, but
|
||||||
|
# on CPython 3.3+ that segfaults. As a workaround, we can temporarily
|
||||||
|
# wrap it in a memoryview, except on Python 2.6 which doesn't have a
|
||||||
|
# memoryview type.
|
||||||
|
try:
|
||||||
|
buffer[:result] = memoryview(_ffi.buffer(buf, result))
|
||||||
|
except NameError:
|
||||||
|
buffer[:result] = _ffi.buffer(buf, result)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
def _handle_bio_errors(self, bio, result):
|
def _handle_bio_errors(self, bio, result):
|
||||||
if _lib.BIO_should_retry(bio):
|
if _lib.BIO_should_retry(bio):
|
||||||
if _lib.BIO_should_read(bio):
|
if _lib.BIO_should_read(bio):
|
||||||
|
@ -1046,6 +1410,8 @@ class Connection(object):
|
||||||
:param buf: The string to put into the memory BIO.
|
:param buf: The string to put into the memory BIO.
|
||||||
:return: The number of bytes written
|
:return: The number of bytes written
|
||||||
"""
|
"""
|
||||||
|
buf = _text_to_bytes_and_warn("buf", buf)
|
||||||
|
|
||||||
if self._into_ssl is None:
|
if self._into_ssl is None:
|
||||||
raise TypeError("Connection sock was not None")
|
raise TypeError("Connection sock was not None")
|
||||||
|
|
||||||
|
@ -1153,8 +1519,7 @@ class Connection(object):
|
||||||
"""
|
"""
|
||||||
result = _lib.SSL_shutdown(self._ssl)
|
result = _lib.SSL_shutdown(self._ssl)
|
||||||
if result < 0:
|
if result < 0:
|
||||||
# TODO: This is untested.
|
self._raise_ssl_error(self._ssl, result)
|
||||||
_raise_current_error()
|
|
||||||
elif result > 0:
|
elif result > 0:
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
|
@ -1210,7 +1575,7 @@ class Connection(object):
|
||||||
The makefile() method is not implemented, since there is no dup semantics
|
The makefile() method is not implemented, since there is no dup semantics
|
||||||
for SSL connections
|
for SSL connections
|
||||||
|
|
||||||
:raise NotImplementedError
|
:raise: NotImplementedError
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError("Cannot make file object of OpenSSL.SSL.Connection")
|
raise NotImplementedError("Cannot make file object of OpenSSL.SSL.Connection")
|
||||||
|
|
||||||
|
@ -1416,6 +1781,166 @@ class Connection(object):
|
||||||
if not result:
|
if not result:
|
||||||
_raise_current_error()
|
_raise_current_error()
|
||||||
|
|
||||||
|
|
||||||
|
def _get_finished_message(self, function):
|
||||||
|
"""
|
||||||
|
Helper to implement :py:meth:`get_finished` and
|
||||||
|
:py:meth:`get_peer_finished`.
|
||||||
|
|
||||||
|
:param function: Either :py:data:`SSL_get_finished`: or
|
||||||
|
:py:data:`SSL_get_peer_finished`.
|
||||||
|
|
||||||
|
:return: :py:data:`None` if the desired message has not yet been
|
||||||
|
received, otherwise the contents of the message.
|
||||||
|
:rtype: :py:class:`bytes` or :py:class:`NoneType`
|
||||||
|
"""
|
||||||
|
# The OpenSSL documentation says nothing about what might happen if the
|
||||||
|
# count argument given is zero. Specifically, it doesn't say whether
|
||||||
|
# the output buffer may be NULL in that case or not. Inspection of the
|
||||||
|
# implementation reveals that it calls memcpy() unconditionally.
|
||||||
|
# Section 7.1.4, paragraph 1 of the C standard suggests that
|
||||||
|
# memcpy(NULL, source, 0) is not guaranteed to produce defined (let
|
||||||
|
# alone desirable) behavior (though it probably does on just about
|
||||||
|
# every implementation...)
|
||||||
|
#
|
||||||
|
# Allocate a tiny buffer to pass in (instead of just passing NULL as
|
||||||
|
# one might expect) for the initial call so as to be safe against this
|
||||||
|
# potentially undefined behavior.
|
||||||
|
empty = _ffi.new("char[]", 0)
|
||||||
|
size = function(self._ssl, empty, 0)
|
||||||
|
if size == 0:
|
||||||
|
# No Finished message so far.
|
||||||
|
return None
|
||||||
|
|
||||||
|
buf = _ffi.new("char[]", size)
|
||||||
|
function(self._ssl, buf, size)
|
||||||
|
return _ffi.buffer(buf, size)[:]
|
||||||
|
|
||||||
|
|
||||||
|
def get_finished(self):
|
||||||
|
"""
|
||||||
|
Obtain the latest `handshake finished` message sent to the peer.
|
||||||
|
|
||||||
|
:return: The contents of the message or :py:obj:`None` if the TLS
|
||||||
|
handshake has not yet completed.
|
||||||
|
:rtype: :py:class:`bytes` or :py:class:`NoneType`
|
||||||
|
"""
|
||||||
|
return self._get_finished_message(_lib.SSL_get_finished)
|
||||||
|
|
||||||
|
|
||||||
|
def get_peer_finished(self):
|
||||||
|
"""
|
||||||
|
Obtain the latest `handshake finished` message received from the peer.
|
||||||
|
|
||||||
|
:return: The contents of the message or :py:obj:`None` if the TLS
|
||||||
|
handshake has not yet completed.
|
||||||
|
:rtype: :py:class:`bytes` or :py:class:`NoneType`
|
||||||
|
"""
|
||||||
|
return self._get_finished_message(_lib.SSL_get_peer_finished)
|
||||||
|
|
||||||
|
|
||||||
|
def get_cipher_name(self):
|
||||||
|
"""
|
||||||
|
Obtain the name of the currently used cipher.
|
||||||
|
|
||||||
|
:returns: The name of the currently used cipher or :py:obj:`None`
|
||||||
|
if no connection has been established.
|
||||||
|
:rtype: :py:class:`unicode` or :py:class:`NoneType`
|
||||||
|
"""
|
||||||
|
cipher = _lib.SSL_get_current_cipher(self._ssl)
|
||||||
|
if cipher == _ffi.NULL:
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
name = _ffi.string(_lib.SSL_CIPHER_get_name(cipher))
|
||||||
|
return name.decode("utf-8")
|
||||||
|
|
||||||
|
|
||||||
|
def get_cipher_bits(self):
|
||||||
|
"""
|
||||||
|
Obtain the number of secret bits of the currently used cipher.
|
||||||
|
|
||||||
|
:returns: The number of secret bits of the currently used cipher
|
||||||
|
or :py:obj:`None` if no connection has been established.
|
||||||
|
:rtype: :py:class:`int` or :py:class:`NoneType`
|
||||||
|
"""
|
||||||
|
cipher = _lib.SSL_get_current_cipher(self._ssl)
|
||||||
|
if cipher == _ffi.NULL:
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
return _lib.SSL_CIPHER_get_bits(cipher, _ffi.NULL)
|
||||||
|
|
||||||
|
|
||||||
|
def get_cipher_version(self):
|
||||||
|
"""
|
||||||
|
Obtain the protocol version of the currently used cipher.
|
||||||
|
|
||||||
|
:returns: The protocol name of the currently used cipher
|
||||||
|
or :py:obj:`None` if no connection has been established.
|
||||||
|
:rtype: :py:class:`unicode` or :py:class:`NoneType`
|
||||||
|
"""
|
||||||
|
cipher = _lib.SSL_get_current_cipher(self._ssl)
|
||||||
|
if cipher == _ffi.NULL:
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
version =_ffi.string(_lib.SSL_CIPHER_get_version(cipher))
|
||||||
|
return version.decode("utf-8")
|
||||||
|
|
||||||
|
|
||||||
|
@_requires_npn
|
||||||
|
def get_next_proto_negotiated(self):
|
||||||
|
"""
|
||||||
|
Get the protocol that was negotiated by NPN.
|
||||||
|
"""
|
||||||
|
data = _ffi.new("unsigned char **")
|
||||||
|
data_len = _ffi.new("unsigned int *")
|
||||||
|
|
||||||
|
_lib.SSL_get0_next_proto_negotiated(self._ssl, data, data_len)
|
||||||
|
|
||||||
|
return _ffi.buffer(data[0], data_len[0])[:]
|
||||||
|
|
||||||
|
@_requires_alpn
|
||||||
|
def set_alpn_protos(self, protos):
|
||||||
|
"""
|
||||||
|
Specify the client's ALPN protocol list.
|
||||||
|
|
||||||
|
These protocols are offered to the server during protocol negotiation.
|
||||||
|
|
||||||
|
:param protos: A list of the protocols to be offered to the server.
|
||||||
|
This list should be a Python list of bytestrings representing the
|
||||||
|
protocols to offer, e.g. ``[b'http/1.1', b'spdy/2']``.
|
||||||
|
"""
|
||||||
|
# Take the list of protocols and join them together, prefixing them
|
||||||
|
# with their lengths.
|
||||||
|
protostr = b''.join(
|
||||||
|
chain.from_iterable((int2byte(len(p)), p) for p in protos)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Build a C string from the list. We don't need to save this off
|
||||||
|
# because OpenSSL immediately copies the data out.
|
||||||
|
input_str = _ffi.new("unsigned char[]", protostr)
|
||||||
|
input_str_len = _ffi.cast("unsigned", len(protostr))
|
||||||
|
_lib.SSL_set_alpn_protos(self._ssl, input_str, input_str_len)
|
||||||
|
|
||||||
|
|
||||||
|
def get_alpn_proto_negotiated(self):
|
||||||
|
"""
|
||||||
|
Get the protocol that was negotiated by ALPN.
|
||||||
|
"""
|
||||||
|
if not _lib.Cryptography_HAS_ALPN:
|
||||||
|
raise NotImplementedError("ALPN not available")
|
||||||
|
|
||||||
|
data = _ffi.new("unsigned char **")
|
||||||
|
data_len = _ffi.new("unsigned int *")
|
||||||
|
|
||||||
|
_lib.SSL_get0_alpn_selected(self._ssl, data, data_len)
|
||||||
|
|
||||||
|
if not data_len:
|
||||||
|
return b''
|
||||||
|
|
||||||
|
return _ffi.buffer(data[0], data_len[0])[:]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ConnectionType = Connection
|
ConnectionType = Connection
|
||||||
|
|
||||||
# This is similar to the initialization calls at the end of OpenSSL/crypto.py
|
# This is similar to the initialization calls at the end of OpenSSL/crypto.py
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
from warnings import warn
|
||||||
|
import sys
|
||||||
|
|
||||||
from six import PY3, binary_type, text_type
|
from six import PY3, binary_type, text_type
|
||||||
|
|
||||||
from cryptography.hazmat.bindings.openssl.binding import Binding
|
from cryptography.hazmat.bindings.openssl.binding import Binding
|
||||||
|
@ -5,11 +8,34 @@ binding = Binding()
|
||||||
ffi = binding.ffi
|
ffi = binding.ffi
|
||||||
lib = binding.lib
|
lib = binding.lib
|
||||||
|
|
||||||
def exception_from_error_queue(exceptionType):
|
|
||||||
def text(charp):
|
|
||||||
|
def text(charp):
|
||||||
|
"""
|
||||||
|
Get a native string type representing of the given CFFI ``char*`` object.
|
||||||
|
|
||||||
|
:param charp: A C-style string represented using CFFI.
|
||||||
|
|
||||||
|
:return: :class:`str`
|
||||||
|
"""
|
||||||
|
if not charp:
|
||||||
|
return ""
|
||||||
return native(ffi.string(charp))
|
return native(ffi.string(charp))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def exception_from_error_queue(exception_type):
|
||||||
|
"""
|
||||||
|
Convert an OpenSSL library failure into a Python exception.
|
||||||
|
|
||||||
|
When a call to the native OpenSSL library fails, this is usually signalled
|
||||||
|
by the return value, and an error code is stored in an error queue
|
||||||
|
associated with the current thread. The err library provides functions to
|
||||||
|
obtain these error codes and textual error messages.
|
||||||
|
"""
|
||||||
|
|
||||||
errors = []
|
errors = []
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
error = lib.ERR_get_error()
|
error = lib.ERR_get_error()
|
||||||
if error == 0:
|
if error == 0:
|
||||||
|
@ -19,7 +45,7 @@ def exception_from_error_queue(exceptionType):
|
||||||
text(lib.ERR_func_error_string(error)),
|
text(lib.ERR_func_error_string(error)),
|
||||||
text(lib.ERR_reason_error_string(error))))
|
text(lib.ERR_reason_error_string(error))))
|
||||||
|
|
||||||
raise exceptionType(errors)
|
raise exception_type(errors)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -45,9 +71,57 @@ def native(s):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def path_string(s):
|
||||||
|
"""
|
||||||
|
Convert a Python string to a :py:class:`bytes` string identifying the same
|
||||||
|
path and which can be passed into an OpenSSL API accepting a filename.
|
||||||
|
|
||||||
|
:param s: An instance of :py:class:`bytes` or :py:class:`unicode`.
|
||||||
|
|
||||||
|
:return: An instance of :py:class:`bytes`.
|
||||||
|
"""
|
||||||
|
if isinstance(s, binary_type):
|
||||||
|
return s
|
||||||
|
elif isinstance(s, text_type):
|
||||||
|
return s.encode(sys.getfilesystemencoding())
|
||||||
|
else:
|
||||||
|
raise TypeError("Path must be represented as bytes or unicode string")
|
||||||
|
|
||||||
|
|
||||||
if PY3:
|
if PY3:
|
||||||
def byte_string(s):
|
def byte_string(s):
|
||||||
return s.encode("charmap")
|
return s.encode("charmap")
|
||||||
else:
|
else:
|
||||||
def byte_string(s):
|
def byte_string(s):
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
# A marker object to observe whether some optional arguments are passed any
|
||||||
|
# value or not.
|
||||||
|
UNSPECIFIED = object()
|
||||||
|
|
||||||
|
_TEXT_WARNING = (
|
||||||
|
text_type.__name__ + " for {0} is no longer accepted, use bytes"
|
||||||
|
)
|
||||||
|
|
||||||
|
def text_to_bytes_and_warn(label, obj):
|
||||||
|
"""
|
||||||
|
If ``obj`` is text, emit a warning that it should be bytes instead and try
|
||||||
|
to convert it to bytes automatically.
|
||||||
|
|
||||||
|
:param str label: The name of the parameter from which ``obj`` was taken
|
||||||
|
(so a developer can easily find the source of the problem and correct
|
||||||
|
it).
|
||||||
|
|
||||||
|
:return: If ``obj`` is the text string type, a ``bytes`` object giving the
|
||||||
|
UTF-8 encoding of that text is returned. Otherwise, ``obj`` itself is
|
||||||
|
returned.
|
||||||
|
"""
|
||||||
|
if isinstance(obj, text_type):
|
||||||
|
warn(
|
||||||
|
_TEXT_WARNING.format(label),
|
||||||
|
category=DeprecationWarning,
|
||||||
|
stacklevel=3
|
||||||
|
)
|
||||||
|
return obj.encode('utf-8')
|
||||||
|
return obj
|
||||||
|
|
|
@ -2,17 +2,22 @@ from time import time
|
||||||
from base64 import b16encode
|
from base64 import b16encode
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from operator import __eq__, __ne__, __lt__, __le__, __gt__, __ge__
|
from operator import __eq__, __ne__, __lt__, __le__, __gt__, __ge__
|
||||||
|
from warnings import warn as _warn
|
||||||
|
|
||||||
from six import (
|
from six import (
|
||||||
integer_types as _integer_types,
|
integer_types as _integer_types,
|
||||||
text_type as _text_type)
|
text_type as _text_type,
|
||||||
|
PY3 as _PY3)
|
||||||
|
|
||||||
from OpenSSL._util import (
|
from OpenSSL._util import (
|
||||||
ffi as _ffi,
|
ffi as _ffi,
|
||||||
lib as _lib,
|
lib as _lib,
|
||||||
exception_from_error_queue as _exception_from_error_queue,
|
exception_from_error_queue as _exception_from_error_queue,
|
||||||
byte_string as _byte_string,
|
byte_string as _byte_string,
|
||||||
native as _native)
|
native as _native,
|
||||||
|
UNSPECIFIED as _UNSPECIFIED,
|
||||||
|
text_to_bytes_and_warn as _text_to_bytes_and_warn,
|
||||||
|
)
|
||||||
|
|
||||||
FILETYPE_PEM = _lib.SSL_FILETYPE_PEM
|
FILETYPE_PEM = _lib.SSL_FILETYPE_PEM
|
||||||
FILETYPE_ASN1 = _lib.SSL_FILETYPE_ASN1
|
FILETYPE_ASN1 = _lib.SSL_FILETYPE_ASN1
|
||||||
|
@ -24,6 +29,7 @@ TYPE_RSA = _lib.EVP_PKEY_RSA
|
||||||
TYPE_DSA = _lib.EVP_PKEY_DSA
|
TYPE_DSA = _lib.EVP_PKEY_DSA
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Error(Exception):
|
class Error(Exception):
|
||||||
"""
|
"""
|
||||||
An error occurred in an `OpenSSL.crypto` API.
|
An error occurred in an `OpenSSL.crypto` API.
|
||||||
|
@ -32,6 +38,8 @@ class Error(Exception):
|
||||||
|
|
||||||
_raise_current_error = partial(_exception_from_error_queue, Error)
|
_raise_current_error = partial(_exception_from_error_queue, Error)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def _untested_error(where):
|
def _untested_error(where):
|
||||||
"""
|
"""
|
||||||
An OpenSSL API failed somehow. Additionally, the failure which was
|
An OpenSSL API failed somehow. Additionally, the failure which was
|
||||||
|
@ -263,6 +271,156 @@ PKeyType = PKey
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class _EllipticCurve(object):
|
||||||
|
"""
|
||||||
|
A representation of a supported elliptic curve.
|
||||||
|
|
||||||
|
@cvar _curves: :py:obj:`None` until an attempt is made to load the curves.
|
||||||
|
Thereafter, a :py:type:`set` containing :py:type:`_EllipticCurve`
|
||||||
|
instances each of which represents one curve supported by the system.
|
||||||
|
@type _curves: :py:type:`NoneType` or :py:type:`set`
|
||||||
|
"""
|
||||||
|
_curves = None
|
||||||
|
|
||||||
|
if _PY3:
|
||||||
|
# This only necessary on Python 3. Morever, it is broken on Python 2.
|
||||||
|
def __ne__(self, other):
|
||||||
|
"""
|
||||||
|
Implement cooperation with the right-hand side argument of ``!=``.
|
||||||
|
|
||||||
|
Python 3 seems to have dropped this cooperation in this very narrow
|
||||||
|
circumstance.
|
||||||
|
"""
|
||||||
|
if isinstance(other, _EllipticCurve):
|
||||||
|
return super(_EllipticCurve, self).__ne__(other)
|
||||||
|
return NotImplemented
|
||||||
|
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _load_elliptic_curves(cls, lib):
|
||||||
|
"""
|
||||||
|
Get the curves supported by OpenSSL.
|
||||||
|
|
||||||
|
:param lib: The OpenSSL library binding object.
|
||||||
|
|
||||||
|
:return: A :py:type:`set` of ``cls`` instances giving the names of the
|
||||||
|
elliptic curves the underlying library supports.
|
||||||
|
"""
|
||||||
|
if lib.Cryptography_HAS_EC:
|
||||||
|
num_curves = lib.EC_get_builtin_curves(_ffi.NULL, 0)
|
||||||
|
builtin_curves = _ffi.new('EC_builtin_curve[]', num_curves)
|
||||||
|
# The return value on this call should be num_curves again. We could
|
||||||
|
# check it to make sure but if it *isn't* then.. what could we do?
|
||||||
|
# Abort the whole process, I suppose...? -exarkun
|
||||||
|
lib.EC_get_builtin_curves(builtin_curves, num_curves)
|
||||||
|
return set(
|
||||||
|
cls.from_nid(lib, c.nid)
|
||||||
|
for c in builtin_curves)
|
||||||
|
return set()
|
||||||
|
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _get_elliptic_curves(cls, lib):
|
||||||
|
"""
|
||||||
|
Get, cache, and return the curves supported by OpenSSL.
|
||||||
|
|
||||||
|
:param lib: The OpenSSL library binding object.
|
||||||
|
|
||||||
|
:return: A :py:type:`set` of ``cls`` instances giving the names of the
|
||||||
|
elliptic curves the underlying library supports.
|
||||||
|
"""
|
||||||
|
if cls._curves is None:
|
||||||
|
cls._curves = cls._load_elliptic_curves(lib)
|
||||||
|
return cls._curves
|
||||||
|
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_nid(cls, lib, nid):
|
||||||
|
"""
|
||||||
|
Instantiate a new :py:class:`_EllipticCurve` associated with the given
|
||||||
|
OpenSSL NID.
|
||||||
|
|
||||||
|
:param lib: The OpenSSL library binding object.
|
||||||
|
|
||||||
|
:param nid: The OpenSSL NID the resulting curve object will represent.
|
||||||
|
This must be a curve NID (and not, for example, a hash NID) or
|
||||||
|
subsequent operations will fail in unpredictable ways.
|
||||||
|
:type nid: :py:class:`int`
|
||||||
|
|
||||||
|
:return: The curve object.
|
||||||
|
"""
|
||||||
|
return cls(lib, nid, _ffi.string(lib.OBJ_nid2sn(nid)).decode("ascii"))
|
||||||
|
|
||||||
|
|
||||||
|
def __init__(self, lib, nid, name):
|
||||||
|
"""
|
||||||
|
:param _lib: The :py:mod:`cryptography` binding instance used to
|
||||||
|
interface with OpenSSL.
|
||||||
|
|
||||||
|
:param _nid: The OpenSSL NID identifying the curve this object
|
||||||
|
represents.
|
||||||
|
:type _nid: :py:class:`int`
|
||||||
|
|
||||||
|
:param name: The OpenSSL short name identifying the curve this object
|
||||||
|
represents.
|
||||||
|
:type name: :py:class:`unicode`
|
||||||
|
"""
|
||||||
|
self._lib = lib
|
||||||
|
self._nid = nid
|
||||||
|
self.name = name
|
||||||
|
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "<Curve %r>" % (self.name,)
|
||||||
|
|
||||||
|
|
||||||
|
def _to_EC_KEY(self):
|
||||||
|
"""
|
||||||
|
Create a new OpenSSL EC_KEY structure initialized to use this curve.
|
||||||
|
|
||||||
|
The structure is automatically garbage collected when the Python object
|
||||||
|
is garbage collected.
|
||||||
|
"""
|
||||||
|
key = self._lib.EC_KEY_new_by_curve_name(self._nid)
|
||||||
|
return _ffi.gc(key, _lib.EC_KEY_free)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def get_elliptic_curves():
|
||||||
|
"""
|
||||||
|
Return a set of objects representing the elliptic curves supported in the
|
||||||
|
OpenSSL build in use.
|
||||||
|
|
||||||
|
The curve objects have a :py:class:`unicode` ``name`` attribute by which
|
||||||
|
they identify themselves.
|
||||||
|
|
||||||
|
The curve objects are useful as values for the argument accepted by
|
||||||
|
:py:meth:`Context.set_tmp_ecdh` to specify which elliptical curve should be
|
||||||
|
used for ECDHE key exchange.
|
||||||
|
"""
|
||||||
|
return _EllipticCurve._get_elliptic_curves(_lib)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def get_elliptic_curve(name):
|
||||||
|
"""
|
||||||
|
Return a single curve object selected by name.
|
||||||
|
|
||||||
|
See :py:func:`get_elliptic_curves` for information about curve objects.
|
||||||
|
|
||||||
|
:param name: The OpenSSL short name identifying the curve object to
|
||||||
|
retrieve.
|
||||||
|
:type name: :py:class:`unicode`
|
||||||
|
|
||||||
|
If the named curve is not supported then :py:class:`ValueError` is raised.
|
||||||
|
"""
|
||||||
|
for curve in get_elliptic_curves():
|
||||||
|
if curve.name == name:
|
||||||
|
return curve
|
||||||
|
raise ValueError("unknown curve name", name)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class X509Name(object):
|
class X509Name(object):
|
||||||
def __init__(self, name):
|
def __init__(self, name):
|
||||||
"""
|
"""
|
||||||
|
@ -697,6 +855,21 @@ class X509Req(object):
|
||||||
_raise_current_error()
|
_raise_current_error()
|
||||||
|
|
||||||
|
|
||||||
|
def get_extensions(self):
|
||||||
|
"""
|
||||||
|
Get extensions to the request.
|
||||||
|
|
||||||
|
:return: A :py:class:`list` of :py:class:`X509Extension` objects.
|
||||||
|
"""
|
||||||
|
exts = []
|
||||||
|
native_exts_obj = _lib.X509_REQ_get_extensions(self._req)
|
||||||
|
for i in range(_lib.sk_X509_EXTENSION_num(native_exts_obj)):
|
||||||
|
ext = X509Extension.__new__(X509Extension)
|
||||||
|
ext._extension = _lib.sk_X509_EXTENSION_value(native_exts_obj, i)
|
||||||
|
exts.append(ext)
|
||||||
|
return exts
|
||||||
|
|
||||||
|
|
||||||
def sign(self, pkey, digest):
|
def sign(self, pkey, digest):
|
||||||
"""
|
"""
|
||||||
Sign the certificate request using the supplied key and digest
|
Sign the certificate request using the supplied key and digest
|
||||||
|
@ -1190,6 +1363,125 @@ class X509Store(object):
|
||||||
X509StoreType = X509Store
|
X509StoreType = X509Store
|
||||||
|
|
||||||
|
|
||||||
|
class X509StoreContextError(Exception):
|
||||||
|
"""
|
||||||
|
An error occurred while verifying a certificate using
|
||||||
|
`OpenSSL.X509StoreContext.verify_certificate`.
|
||||||
|
|
||||||
|
:ivar certificate: The certificate which caused verificate failure.
|
||||||
|
:type cert: :class:`X509`
|
||||||
|
|
||||||
|
"""
|
||||||
|
def __init__(self, message, certificate):
|
||||||
|
super(X509StoreContextError, self).__init__(message)
|
||||||
|
self.certificate = certificate
|
||||||
|
|
||||||
|
|
||||||
|
class X509StoreContext(object):
|
||||||
|
"""
|
||||||
|
An X.509 store context.
|
||||||
|
|
||||||
|
An :py:class:`X509StoreContext` is used to define some of the criteria for
|
||||||
|
certificate verification. The information encapsulated in this object
|
||||||
|
includes, but is not limited to, a set of trusted certificates,
|
||||||
|
verification parameters, and revoked certificates.
|
||||||
|
|
||||||
|
Of these, only the set of trusted certificates is currently exposed.
|
||||||
|
|
||||||
|
:ivar _store_ctx: The underlying X509_STORE_CTX structure used by this
|
||||||
|
instance. It is dynamically allocated and automatically garbage
|
||||||
|
collected.
|
||||||
|
|
||||||
|
:ivar _store: See the ``store`` ``__init__`` parameter.
|
||||||
|
|
||||||
|
:ivar _cert: See the ``certificate`` ``__init__`` parameter.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, store, certificate):
|
||||||
|
"""
|
||||||
|
:param X509Store store: The certificates which will be trusted for the
|
||||||
|
purposes of any verifications.
|
||||||
|
|
||||||
|
:param X509 certificate: The certificate to be verified.
|
||||||
|
"""
|
||||||
|
store_ctx = _lib.X509_STORE_CTX_new()
|
||||||
|
self._store_ctx = _ffi.gc(store_ctx, _lib.X509_STORE_CTX_free)
|
||||||
|
self._store = store
|
||||||
|
self._cert = certificate
|
||||||
|
# Make the store context available for use after instantiating this
|
||||||
|
# class by initializing it now. Per testing, subsequent calls to
|
||||||
|
# :py:meth:`_init` have no adverse affect.
|
||||||
|
self._init()
|
||||||
|
|
||||||
|
|
||||||
|
def _init(self):
|
||||||
|
"""
|
||||||
|
Set up the store context for a subsequent verification operation.
|
||||||
|
"""
|
||||||
|
ret = _lib.X509_STORE_CTX_init(self._store_ctx, self._store._store, self._cert._x509, _ffi.NULL)
|
||||||
|
if ret <= 0:
|
||||||
|
_raise_current_error()
|
||||||
|
|
||||||
|
|
||||||
|
def _cleanup(self):
|
||||||
|
"""
|
||||||
|
Internally cleans up the store context.
|
||||||
|
|
||||||
|
The store context can then be reused with a new call to
|
||||||
|
:py:meth:`_init`.
|
||||||
|
"""
|
||||||
|
_lib.X509_STORE_CTX_cleanup(self._store_ctx)
|
||||||
|
|
||||||
|
|
||||||
|
def _exception_from_context(self):
|
||||||
|
"""
|
||||||
|
Convert an OpenSSL native context error failure into a Python
|
||||||
|
exception.
|
||||||
|
|
||||||
|
When a call to native OpenSSL X509_verify_cert fails, additonal information
|
||||||
|
about the failure can be obtained from the store context.
|
||||||
|
"""
|
||||||
|
errors = [
|
||||||
|
_lib.X509_STORE_CTX_get_error(self._store_ctx),
|
||||||
|
_lib.X509_STORE_CTX_get_error_depth(self._store_ctx),
|
||||||
|
_native(_ffi.string(_lib.X509_verify_cert_error_string(
|
||||||
|
_lib.X509_STORE_CTX_get_error(self._store_ctx)))),
|
||||||
|
]
|
||||||
|
# A context error should always be associated with a certificate, so we
|
||||||
|
# expect this call to never return :class:`None`.
|
||||||
|
_x509 = _lib.X509_STORE_CTX_get_current_cert(self._store_ctx)
|
||||||
|
_cert = _lib.X509_dup(_x509)
|
||||||
|
pycert = X509.__new__(X509)
|
||||||
|
pycert._x509 = _ffi.gc(_cert, _lib.X509_free)
|
||||||
|
return X509StoreContextError(errors, pycert)
|
||||||
|
|
||||||
|
|
||||||
|
def set_store(self, store):
|
||||||
|
"""
|
||||||
|
Set the context's trust store.
|
||||||
|
|
||||||
|
:param X509Store store: The certificates which will be trusted for the
|
||||||
|
purposes of any *future* verifications.
|
||||||
|
"""
|
||||||
|
self._store = store
|
||||||
|
|
||||||
|
|
||||||
|
def verify_certificate(self):
|
||||||
|
"""
|
||||||
|
Verify a certificate in a context.
|
||||||
|
|
||||||
|
:param store_ctx: The :py:class:`X509StoreContext` to verify.
|
||||||
|
:raises: Error
|
||||||
|
"""
|
||||||
|
# Always re-initialize the store context in case
|
||||||
|
# :py:meth:`verify_certificate` is called multiple times.
|
||||||
|
self._init()
|
||||||
|
ret = _lib.X509_verify_cert(self._store_ctx)
|
||||||
|
self._cleanup()
|
||||||
|
if ret <= 0:
|
||||||
|
raise self._exception_from_context()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def load_certificate(type, buffer):
|
def load_certificate(type, buffer):
|
||||||
"""
|
"""
|
||||||
|
@ -1308,9 +1600,11 @@ def _X509_REVOKED_dup(original):
|
||||||
_raise_current_error()
|
_raise_current_error()
|
||||||
|
|
||||||
if original.serialNumber != _ffi.NULL:
|
if original.serialNumber != _ffi.NULL:
|
||||||
|
_lib.ASN1_INTEGER_free(copy.serialNumber)
|
||||||
copy.serialNumber = _lib.ASN1_INTEGER_dup(original.serialNumber)
|
copy.serialNumber = _lib.ASN1_INTEGER_dup(original.serialNumber)
|
||||||
|
|
||||||
if original.revocationDate != _ffi.NULL:
|
if original.revocationDate != _ffi.NULL:
|
||||||
|
_lib.ASN1_TIME_free(copy.revocationDate)
|
||||||
copy.revocationDate = _lib.M_ASN1_TIME_dup(original.revocationDate)
|
copy.revocationDate = _lib.M_ASN1_TIME_dup(original.revocationDate)
|
||||||
|
|
||||||
if original.extensions != _ffi.NULL:
|
if original.extensions != _ffi.NULL:
|
||||||
|
@ -1539,7 +1833,8 @@ class CRL(object):
|
||||||
_raise_current_error()
|
_raise_current_error()
|
||||||
|
|
||||||
|
|
||||||
def export(self, cert, key, type=FILETYPE_PEM, days=100):
|
def export(self, cert, key, type=FILETYPE_PEM, days=100,
|
||||||
|
digest=_UNSPECIFIED):
|
||||||
"""
|
"""
|
||||||
export a CRL as a string
|
export a CRL as a string
|
||||||
|
|
||||||
|
@ -1549,12 +1844,15 @@ class CRL(object):
|
||||||
:param key: Used to sign CRL.
|
:param key: Used to sign CRL.
|
||||||
:type key: :class:`PKey`
|
:type key: :class:`PKey`
|
||||||
|
|
||||||
:param type: The export format, either :py:data:`FILETYPE_PEM`, :py:data:`FILETYPE_ASN1`, or :py:data:`FILETYPE_TEXT`.
|
:param type: The export format, either :py:data:`FILETYPE_PEM`,
|
||||||
|
:py:data:`FILETYPE_ASN1`, or :py:data:`FILETYPE_TEXT`.
|
||||||
|
|
||||||
:param days: The number of days until the next update of this CRL.
|
:param int days: The number of days until the next update of this CRL.
|
||||||
:type days: :py:data:`int`
|
|
||||||
|
|
||||||
:return: :py:data:`str`
|
:param bytes digest: The name of the message digest to use (eg
|
||||||
|
``b"sha1"``).
|
||||||
|
|
||||||
|
:return: :py:data:`bytes`
|
||||||
"""
|
"""
|
||||||
if not isinstance(cert, X509):
|
if not isinstance(cert, X509):
|
||||||
raise TypeError("cert must be an X509 instance")
|
raise TypeError("cert must be an X509 instance")
|
||||||
|
@ -1563,6 +1861,19 @@ class CRL(object):
|
||||||
if not isinstance(type, int):
|
if not isinstance(type, int):
|
||||||
raise TypeError("type must be an integer")
|
raise TypeError("type must be an integer")
|
||||||
|
|
||||||
|
if digest is _UNSPECIFIED:
|
||||||
|
_warn(
|
||||||
|
"The default message digest (md5) is deprecated. "
|
||||||
|
"Pass the name of a message digest explicitly.",
|
||||||
|
category=DeprecationWarning,
|
||||||
|
stacklevel=2,
|
||||||
|
)
|
||||||
|
digest = b"md5"
|
||||||
|
|
||||||
|
digest_obj = _lib.EVP_get_digestbyname(digest)
|
||||||
|
if digest_obj == _ffi.NULL:
|
||||||
|
raise ValueError("No such digest method")
|
||||||
|
|
||||||
bio = _lib.BIO_new(_lib.BIO_s_mem())
|
bio = _lib.BIO_new(_lib.BIO_s_mem())
|
||||||
if bio == _ffi.NULL:
|
if bio == _ffi.NULL:
|
||||||
# TODO: This is untested.
|
# TODO: This is untested.
|
||||||
|
@ -1582,7 +1893,7 @@ class CRL(object):
|
||||||
|
|
||||||
_lib.X509_CRL_set_issuer_name(self._crl, _lib.X509_get_subject_name(cert._x509))
|
_lib.X509_CRL_set_issuer_name(self._crl, _lib.X509_get_subject_name(cert._x509))
|
||||||
|
|
||||||
sign_result = _lib.X509_CRL_sign(self._crl, key._pkey, _lib.EVP_md5())
|
sign_result = _lib.X509_CRL_sign(self._crl, key._pkey, digest_obj)
|
||||||
if not sign_result:
|
if not sign_result:
|
||||||
_raise_current_error()
|
_raise_current_error()
|
||||||
|
|
||||||
|
@ -1729,7 +2040,7 @@ class PKCS12(object):
|
||||||
|
|
||||||
def set_ca_certificates(self, cacerts):
|
def set_ca_certificates(self, cacerts):
|
||||||
"""
|
"""
|
||||||
Replace or set the CA certificates withing the PKCS12 object.
|
Replace or set the CA certificates within the PKCS12 object.
|
||||||
|
|
||||||
:param cacerts: The new CA certificates.
|
:param cacerts: The new CA certificates.
|
||||||
:type cacerts: :py:data:`None` or an iterable of :py:class:`X509`
|
:type cacerts: :py:data:`None` or an iterable of :py:class:`X509`
|
||||||
|
@ -1784,6 +2095,8 @@ class PKCS12(object):
|
||||||
|
|
||||||
:return: The string containing the PKCS12
|
:return: The string containing the PKCS12
|
||||||
"""
|
"""
|
||||||
|
passphrase = _text_to_bytes_and_warn("passphrase", passphrase)
|
||||||
|
|
||||||
if self._cacerts is None:
|
if self._cacerts is None:
|
||||||
cacerts = _ffi.NULL
|
cacerts = _ffi.NULL
|
||||||
else:
|
else:
|
||||||
|
@ -2081,6 +2394,8 @@ def sign(pkey, data, digest):
|
||||||
:param digest: message digest to use
|
:param digest: message digest to use
|
||||||
:return: signature
|
:return: signature
|
||||||
"""
|
"""
|
||||||
|
data = _text_to_bytes_and_warn("data", data)
|
||||||
|
|
||||||
digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
|
digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
|
||||||
if digest_obj == _ffi.NULL:
|
if digest_obj == _ffi.NULL:
|
||||||
raise ValueError("No such digest method")
|
raise ValueError("No such digest method")
|
||||||
|
@ -2115,6 +2430,8 @@ def verify(cert, signature, data, digest):
|
||||||
:param digest: message digest to use
|
:param digest: message digest to use
|
||||||
:return: None if the signature is correct, raise exception otherwise
|
:return: None if the signature is correct, raise exception otherwise
|
||||||
"""
|
"""
|
||||||
|
data = _text_to_bytes_and_warn("data", data)
|
||||||
|
|
||||||
digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
|
digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
|
||||||
if digest_obj == _ffi.NULL:
|
if digest_obj == _ffi.NULL:
|
||||||
raise ValueError("No such digest method")
|
raise ValueError("No such digest method")
|
||||||
|
@ -2136,7 +2453,6 @@ def verify(cert, signature, data, digest):
|
||||||
_raise_current_error()
|
_raise_current_error()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def load_crl(type, buffer):
|
def load_crl(type, buffer):
|
||||||
"""
|
"""
|
||||||
Load a certificate revocation list from a buffer
|
Load a certificate revocation list from a buffer
|
||||||
|
@ -2183,7 +2499,7 @@ def load_pkcs7_data(type, buffer):
|
||||||
if type == FILETYPE_PEM:
|
if type == FILETYPE_PEM:
|
||||||
pkcs7 = _lib.PEM_read_bio_PKCS7(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
|
pkcs7 = _lib.PEM_read_bio_PKCS7(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
|
||||||
elif type == FILETYPE_ASN1:
|
elif type == FILETYPE_ASN1:
|
||||||
pass
|
pkcs7 = _lib.d2i_PKCS7_bio(bio, _ffi.NULL)
|
||||||
else:
|
else:
|
||||||
# TODO: This is untested.
|
# TODO: This is untested.
|
||||||
_raise_current_error()
|
_raise_current_error()
|
||||||
|
@ -2198,7 +2514,7 @@ def load_pkcs7_data(type, buffer):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def load_pkcs12(buffer, passphrase):
|
def load_pkcs12(buffer, passphrase=None):
|
||||||
"""
|
"""
|
||||||
Load a PKCS12 object from a buffer
|
Load a PKCS12 object from a buffer
|
||||||
|
|
||||||
|
@ -2206,11 +2522,20 @@ def load_pkcs12(buffer, passphrase):
|
||||||
:param passphrase: (Optional) The password to decrypt the PKCS12 lump
|
:param passphrase: (Optional) The password to decrypt the PKCS12 lump
|
||||||
:returns: The PKCS12 object
|
:returns: The PKCS12 object
|
||||||
"""
|
"""
|
||||||
|
passphrase = _text_to_bytes_and_warn("passphrase", passphrase)
|
||||||
|
|
||||||
if isinstance(buffer, _text_type):
|
if isinstance(buffer, _text_type):
|
||||||
buffer = buffer.encode("ascii")
|
buffer = buffer.encode("ascii")
|
||||||
|
|
||||||
bio = _new_mem_buf(buffer)
|
bio = _new_mem_buf(buffer)
|
||||||
|
|
||||||
|
# Use null passphrase if passphrase is None or empty string. With PKCS#12
|
||||||
|
# password based encryption no password and a zero length password are two
|
||||||
|
# different things, but OpenSSL implementation will try both to figure out
|
||||||
|
# which one works.
|
||||||
|
if not passphrase:
|
||||||
|
passphrase = _ffi.NULL
|
||||||
|
|
||||||
p12 = _lib.d2i_PKCS12_bio(bio, _ffi.NULL)
|
p12 = _lib.d2i_PKCS12_bio(bio, _ffi.NULL)
|
||||||
if p12 == _ffi.NULL:
|
if p12 == _ffi.NULL:
|
||||||
_raise_current_error()
|
_raise_current_error()
|
||||||
|
|
|
@ -11,7 +11,8 @@ from six import integer_types as _integer_types
|
||||||
from OpenSSL._util import (
|
from OpenSSL._util import (
|
||||||
ffi as _ffi,
|
ffi as _ffi,
|
||||||
lib as _lib,
|
lib as _lib,
|
||||||
exception_from_error_queue as _exception_from_error_queue)
|
exception_from_error_queue as _exception_from_error_queue,
|
||||||
|
path_string as _path_string)
|
||||||
|
|
||||||
|
|
||||||
class Error(Exception):
|
class Error(Exception):
|
||||||
|
@ -131,13 +132,13 @@ def load_file(filename, maxbytes=_unspecified):
|
||||||
"""
|
"""
|
||||||
Seed the PRNG with data from a file
|
Seed the PRNG with data from a file
|
||||||
|
|
||||||
:param filename: The file to read data from
|
:param filename: The file to read data from (``bytes`` or ``unicode``).
|
||||||
:param maxbytes: (optional) The number of bytes to read, default is
|
:param maxbytes: (optional) The number of bytes to read, default is to read
|
||||||
to read the entire file
|
the entire file
|
||||||
|
|
||||||
:return: The number of bytes read
|
:return: The number of bytes read
|
||||||
"""
|
"""
|
||||||
if not isinstance(filename, _builtin_bytes):
|
filename = _path_string(filename)
|
||||||
raise TypeError("filename must be a string")
|
|
||||||
|
|
||||||
if maxbytes is _unspecified:
|
if maxbytes is _unspecified:
|
||||||
maxbytes = -1
|
maxbytes = -1
|
||||||
|
@ -152,12 +153,11 @@ def write_file(filename):
|
||||||
"""
|
"""
|
||||||
Save PRNG state to a file
|
Save PRNG state to a file
|
||||||
|
|
||||||
:param filename: The file to write data to
|
:param filename: The file to write data to (``bytes`` or ``unicode``).
|
||||||
|
|
||||||
:return: The number of bytes written
|
:return: The number of bytes written
|
||||||
"""
|
"""
|
||||||
if not isinstance(filename, _builtin_bytes):
|
filename = _path_string(filename)
|
||||||
raise TypeError("filename must be a string")
|
|
||||||
|
|
||||||
return _lib.RAND_write_file(filename)
|
return _lib.RAND_write_file(filename)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -6,16 +6,22 @@ Unit tests for :py:mod:`OpenSSL.crypto`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from unittest import main
|
from unittest import main
|
||||||
|
from warnings import catch_warnings, simplefilter
|
||||||
|
|
||||||
import os, re
|
import base64
|
||||||
|
import os
|
||||||
|
import re
|
||||||
from subprocess import PIPE, Popen
|
from subprocess import PIPE, Popen
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
from six import binary_type
|
from six import u, b, binary_type, PY3
|
||||||
|
from warnings import simplefilter
|
||||||
|
from warnings import catch_warnings
|
||||||
|
|
||||||
from OpenSSL.crypto import TYPE_RSA, TYPE_DSA, Error, PKey, PKeyType
|
from OpenSSL.crypto import TYPE_RSA, TYPE_DSA, Error, PKey, PKeyType
|
||||||
from OpenSSL.crypto import X509, X509Type, X509Name, X509NameType
|
from OpenSSL.crypto import X509, X509Type, X509Name, X509NameType
|
||||||
from OpenSSL.crypto import X509Store, X509StoreType, X509Req, X509ReqType
|
from OpenSSL.crypto import X509Store, X509StoreType, X509StoreContext, X509StoreContextError
|
||||||
|
from OpenSSL.crypto import X509Req, X509ReqType
|
||||||
from OpenSSL.crypto import X509Extension, X509ExtensionType
|
from OpenSSL.crypto import X509Extension, X509ExtensionType
|
||||||
from OpenSSL.crypto import load_certificate, load_privatekey
|
from OpenSSL.crypto import load_certificate, load_privatekey
|
||||||
from OpenSSL.crypto import FILETYPE_PEM, FILETYPE_ASN1, FILETYPE_TEXT
|
from OpenSSL.crypto import FILETYPE_PEM, FILETYPE_ASN1, FILETYPE_TEXT
|
||||||
|
@ -25,9 +31,12 @@ from OpenSSL.crypto import PKCS7Type, load_pkcs7_data
|
||||||
from OpenSSL.crypto import PKCS12, PKCS12Type, load_pkcs12
|
from OpenSSL.crypto import PKCS12, PKCS12Type, load_pkcs12
|
||||||
from OpenSSL.crypto import CRL, Revoked, load_crl
|
from OpenSSL.crypto import CRL, Revoked, load_crl
|
||||||
from OpenSSL.crypto import NetscapeSPKI, NetscapeSPKIType
|
from OpenSSL.crypto import NetscapeSPKI, NetscapeSPKIType
|
||||||
from OpenSSL.crypto import sign, verify
|
from OpenSSL.crypto import (
|
||||||
from OpenSSL.test.util import TestCase, b
|
sign, verify, get_elliptic_curve, get_elliptic_curves)
|
||||||
from OpenSSL._util import native
|
from OpenSSL.test.util import (
|
||||||
|
EqualityTestsMixin, TestCase, WARNING_TYPE_EXPECTED
|
||||||
|
)
|
||||||
|
from OpenSSL._util import native, lib
|
||||||
|
|
||||||
def normalize_certificate_pem(pem):
|
def normalize_certificate_pem(pem):
|
||||||
return dump_certificate(FILETYPE_PEM, load_certificate(FILETYPE_PEM, pem))
|
return dump_certificate(FILETYPE_PEM, load_certificate(FILETYPE_PEM, pem))
|
||||||
|
@ -80,6 +89,40 @@ cbvAhow217X9V0dVerEOKxnNYspXRrh36h7k4mQA+sDq
|
||||||
-----END RSA PRIVATE KEY-----
|
-----END RSA PRIVATE KEY-----
|
||||||
""")
|
""")
|
||||||
|
|
||||||
|
intermediate_cert_pem = b("""-----BEGIN CERTIFICATE-----
|
||||||
|
MIICVzCCAcCgAwIBAgIRAMPzhm6//0Y/g2pmnHR2C4cwDQYJKoZIhvcNAQENBQAw
|
||||||
|
WDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQHEwdDaGljYWdvMRAw
|
||||||
|
DgYDVQQKEwdUZXN0aW5nMRgwFgYDVQQDEw9UZXN0aW5nIFJvb3QgQ0EwHhcNMTQw
|
||||||
|
ODI4MDIwNDA4WhcNMjQwODI1MDIwNDA4WjBmMRUwEwYDVQQDEwxpbnRlcm1lZGlh
|
||||||
|
dGUxDDAKBgNVBAoTA29yZzERMA8GA1UECxMIb3JnLXVuaXQxCzAJBgNVBAYTAlVT
|
||||||
|
MQswCQYDVQQIEwJDQTESMBAGA1UEBxMJU2FuIERpZWdvMIGfMA0GCSqGSIb3DQEB
|
||||||
|
AQUAA4GNADCBiQKBgQDYcEQw5lfbEQRjr5Yy4yxAHGV0b9Al+Lmu7wLHMkZ/ZMmK
|
||||||
|
FGIbljbviiD1Nz97Oh2cpB91YwOXOTN2vXHq26S+A5xe8z/QJbBsyghMur88CjdT
|
||||||
|
21H2qwMa+r5dCQwEhuGIiZ3KbzB/n4DTMYI5zy4IYPv0pjxShZn4aZTCCK2IUwID
|
||||||
|
AQABoxMwETAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBDQUAA4GBAPIWSkLX
|
||||||
|
QRMApOjjyC+tMxumT5e2pMqChHmxobQK4NMdrf2VCx+cRT6EmY8sK3/Xl/X8UBQ+
|
||||||
|
9n5zXb1ZwhW/sTWgUvmOceJ4/XVs9FkdWOOn1J0XBch9ZIiFe/s5ASIgG7fUdcUF
|
||||||
|
9mAWS6FK2ca3xIh5kIupCXOFa0dPvlw/YUFT
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
""")
|
||||||
|
|
||||||
|
intermediate_key_pem = b("""-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
MIICWwIBAAKBgQDYcEQw5lfbEQRjr5Yy4yxAHGV0b9Al+Lmu7wLHMkZ/ZMmKFGIb
|
||||||
|
ljbviiD1Nz97Oh2cpB91YwOXOTN2vXHq26S+A5xe8z/QJbBsyghMur88CjdT21H2
|
||||||
|
qwMa+r5dCQwEhuGIiZ3KbzB/n4DTMYI5zy4IYPv0pjxShZn4aZTCCK2IUwIDAQAB
|
||||||
|
AoGAfSZVV80pSeOKHTYfbGdNY/jHdU9eFUa/33YWriXU+77EhpIItJjkRRgivIfo
|
||||||
|
rhFJpBSGmDLblaqepm8emsXMeH4+2QzOYIf0QGGP6E6scjTt1PLqdqKfVJ1a2REN
|
||||||
|
147cujNcmFJb/5VQHHMpaPTgttEjlzuww4+BCDPsVRABWrkCQQD3loH36nLoQTtf
|
||||||
|
+kQq0T6Bs9/UWkTAGo0ND81ALj0F8Ie1oeZg6RNT96RxZ3aVuFTESTv6/TbjWywO
|
||||||
|
wdzlmV1vAkEA38rTJ6PTwaJlw5OttdDzAXGPB9tDmzh9oSi7cHwQQXizYd8MBYx4
|
||||||
|
sjHUKD3dCQnb1dxJFhd3BT5HsnkRMbVZXQJAbXduH17ZTzcIOXc9jHDXYiFVZV5D
|
||||||
|
52vV0WCbLzVCZc3jMrtSUKa8lPN5EWrdU3UchWybyG0MR5mX8S5lrF4SoQJAIyUD
|
||||||
|
DBKaSqpqONCUUx1BTFS9FYrFjzbL4+c1qHCTTPTblt8kUCrDOZjBrKAqeiTmNSum
|
||||||
|
/qUot9YUBF8m6BuGsQJATHHmdFy/fG1VLkyBp49CAa8tN3Z5r/CgTznI4DfMTf4C
|
||||||
|
NbRHn2UmYlwQBa+L5lg9phewNe8aEwpPyPLoV85U8Q==
|
||||||
|
-----END RSA PRIVATE KEY-----
|
||||||
|
""")
|
||||||
|
|
||||||
server_cert_pem = b("""-----BEGIN CERTIFICATE-----
|
server_cert_pem = b("""-----BEGIN CERTIFICATE-----
|
||||||
MIICKDCCAZGgAwIBAgIJAJn/HpR21r/8MA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNV
|
MIICKDCCAZGgAwIBAgIJAJn/HpR21r/8MA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNV
|
||||||
BAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UEBxMHQ2hpY2FnbzEQMA4GA1UEChMH
|
BAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UEBxMHQ2hpY2FnbzEQMA4GA1UEChMH
|
||||||
|
@ -113,6 +156,40 @@ r50+LF74iLXFwqysVCebPKMOpDWp/qQ1BbJQIPs7/A==
|
||||||
-----END RSA PRIVATE KEY-----
|
-----END RSA PRIVATE KEY-----
|
||||||
"""))
|
"""))
|
||||||
|
|
||||||
|
intermediate_server_cert_pem = b("""-----BEGIN CERTIFICATE-----
|
||||||
|
MIICWDCCAcGgAwIBAgIRAPQFY9jfskSihdiNSNdt6GswDQYJKoZIhvcNAQENBQAw
|
||||||
|
ZjEVMBMGA1UEAxMMaW50ZXJtZWRpYXRlMQwwCgYDVQQKEwNvcmcxETAPBgNVBAsT
|
||||||
|
CG9yZy11bml0MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEjAQBgNVBAcTCVNh
|
||||||
|
biBEaWVnbzAeFw0xNDA4MjgwMjEwNDhaFw0yNDA4MjUwMjEwNDhaMG4xHTAbBgNV
|
||||||
|
BAMTFGludGVybWVkaWF0ZS1zZXJ2aWNlMQwwCgYDVQQKEwNvcmcxETAPBgNVBAsT
|
||||||
|
CG9yZy11bml0MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEjAQBgNVBAcTCVNh
|
||||||
|
biBEaWVnbzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAqpJZygd+w1faLOr1
|
||||||
|
iOAmbBhx5SZWcTCZ/ZjHQTJM7GuPT624QkqsixFghRKdDROwpwnAP7gMRukLqiy4
|
||||||
|
+kRuGT5OfyGggL95i2xqA+zehjj08lSTlvGHpePJgCyTavIy5+Ljsj4DKnKyuhxm
|
||||||
|
biXTRrH83NDgixVkObTEmh/OVK0CAwEAATANBgkqhkiG9w0BAQ0FAAOBgQBa0Npw
|
||||||
|
UkzjaYEo1OUE1sTI6Mm4riTIHMak4/nswKh9hYup//WVOlr/RBSBtZ7Q/BwbjobN
|
||||||
|
3bfAtV7eSAqBsfxYXyof7G1ALANQERkq3+oyLP1iVt08W1WOUlIMPhdCF/QuCwy6
|
||||||
|
x9MJLhUCGLJPM+O2rAPWVD9wCmvq10ALsiH3yA==
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
""")
|
||||||
|
|
||||||
|
intermediate_server_key_pem = b("""-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
MIICXAIBAAKBgQCqklnKB37DV9os6vWI4CZsGHHlJlZxMJn9mMdBMkzsa49PrbhC
|
||||||
|
SqyLEWCFEp0NE7CnCcA/uAxG6QuqLLj6RG4ZPk5/IaCAv3mLbGoD7N6GOPTyVJOW
|
||||||
|
8Yel48mALJNq8jLn4uOyPgMqcrK6HGZuJdNGsfzc0OCLFWQ5tMSaH85UrQIDAQAB
|
||||||
|
AoGAIQ594j5zna3/9WaPsTgnmhlesVctt4AAx/n827DA4ayyuHFlXUuVhtoWR5Pk
|
||||||
|
5ezj9mtYW8DyeCegABnsu2vZni/CdvU6uiS1Hv6qM1GyYDm9KWgovIP9rQCDSGaz
|
||||||
|
d57IWVGxx7ODFkm3gN5nxnSBOFVHytuW1J7FBRnEsehRroECQQDXHFOv82JuXDcz
|
||||||
|
z3+4c74IEURdOHcbycxlppmK9kFqm5lsUdydnnGW+mvwDk0APOB7Wg7vyFyr393e
|
||||||
|
dpmBDCzNAkEAyv6tVbTKUYhSjW+QhabJo896/EqQEYUmtMXxk4cQnKeR/Ao84Rkf
|
||||||
|
EqD5IykMUfUI0jJU4DGX+gWZ10a7kNbHYQJAVFCuHNFxS4Cpwo0aqtnzKoZaHY/8
|
||||||
|
X9ABZfafSHCtw3Op92M+7ikkrOELXdS9KdKyyqbKJAKNEHF3LbOfB44WIQJAA2N4
|
||||||
|
9UNNVUsXRbElEnYUS529CdUczo4QdVgQjkvk5RiPAUwSdBd9Q0xYnFOlFwEmIowg
|
||||||
|
ipWJWe0aAlP18ZcEQQJBAL+5lekZ/GUdQoZ4HAsN5a9syrzavJ9VvU1KOOPorPZK
|
||||||
|
nMRZbbQgP+aSB7yl6K0gaLaZ8XaK0pjxNBh6ASqg9f4=
|
||||||
|
-----END RSA PRIVATE KEY-----
|
||||||
|
""")
|
||||||
|
|
||||||
client_cert_pem = b("""-----BEGIN CERTIFICATE-----
|
client_cert_pem = b("""-----BEGIN CERTIFICATE-----
|
||||||
MIICJjCCAY+gAwIBAgIJAKxpFI5lODkjMA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNV
|
MIICJjCCAY+gAwIBAgIJAKxpFI5lODkjMA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNV
|
||||||
BAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UEBxMHQ2hpY2FnbzEQMA4GA1UEChMH
|
BAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UEBxMHQ2hpY2FnbzEQMA4GA1UEChMH
|
||||||
|
@ -247,6 +324,27 @@ Ho4EzbYCOaEAMQA=
|
||||||
-----END PKCS7-----
|
-----END PKCS7-----
|
||||||
""")
|
""")
|
||||||
|
|
||||||
|
pkcs7DataASN1 = base64.b64decode(b"""
|
||||||
|
MIIDNwYJKoZIhvcNAQcCoIIDKDCCAyQCAQExADALBgkqhkiG9w0BBwGgggMKMIID
|
||||||
|
BjCCAm+gAwIBAgIBATANBgkqhkiG9w0BAQQFADB7MQswCQYDVQQGEwJTRzERMA8G
|
||||||
|
A1UEChMITTJDcnlwdG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQDExtN
|
||||||
|
MkNyeXB0byBDZXJ0aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNA
|
||||||
|
cG9zdDEuY29tMB4XDTAwMDkxMDA5NTEzMFoXDTAyMDkxMDA5NTEzMFowUzELMAkG
|
||||||
|
A1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRIwEAYDVQQDEwlsb2NhbGhvc3Qx
|
||||||
|
HTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tMFwwDQYJKoZIhvcNAQEBBQAD
|
||||||
|
SwAwSAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh5kwI
|
||||||
|
zOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEAAaOCAQQwggEAMAkGA1UdEwQCMAAw
|
||||||
|
LAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0G
|
||||||
|
A1UdDgQWBBTPhIKSvnsmYsBVNWjj0m3M2z0qVTCBpQYDVR0jBIGdMIGagBT7hyNp
|
||||||
|
65w6kxXlxb8pUU/+7Sg4AaF/pH0wezELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0y
|
||||||
|
Q3J5cHRvMRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UEAxMbTTJDcnlwdG8g
|
||||||
|
Q2VydGlmaWNhdGUgTWFzdGVyMR0wGwYJKoZIhvcNAQkBFg5uZ3BzQHBvc3QxLmNv
|
||||||
|
bYIBADANBgkqhkiG9w0BAQQFAAOBgQA7/CqT6PoHycTdhEStWNZde7M/2Yc6BoJu
|
||||||
|
VwnW8YxGO8Sn6UJ4FeffZNcYZddSDKosw8LtPOeWoK3JINjAk5jiPQ2cww++7QGG
|
||||||
|
/g5NDjxFZNDJP1dGiLAxPW6JXwov4v0FmdzfLOZ01jDcgQQZqEpYlgpuI5JEWUQ9
|
||||||
|
Ho4EzbYCOaEAMQA=
|
||||||
|
""")
|
||||||
|
|
||||||
crlData = b("""\
|
crlData = b("""\
|
||||||
-----BEGIN X509 CRL-----
|
-----BEGIN X509 CRL-----
|
||||||
MIIBWzCBxTANBgkqhkiG9w0BAQQFADBYMQswCQYDVQQGEwJVUzELMAkGA1UECBMC
|
MIIBWzCBxTANBgkqhkiG9w0BAQQFADBYMQswCQYDVQQGEwJVUzELMAkGA1UECBMC
|
||||||
|
@ -512,7 +610,7 @@ class X509ExtTests(TestCase):
|
||||||
|
|
||||||
def test_issuer(self):
|
def test_issuer(self):
|
||||||
"""
|
"""
|
||||||
If an extension requires a issuer, the :py:data:`issuer` parameter to
|
If an extension requires an issuer, the :py:data:`issuer` parameter to
|
||||||
:py:class:`X509Extension` provides its value.
|
:py:class:`X509Extension` provides its value.
|
||||||
"""
|
"""
|
||||||
ext2 = X509Extension(
|
ext2 = X509Extension(
|
||||||
|
@ -1108,7 +1206,32 @@ class X509ReqTests(TestCase, _PKeyInteractionTestsMixin):
|
||||||
request = X509Req()
|
request = X509Req()
|
||||||
request.add_extensions([
|
request.add_extensions([
|
||||||
X509Extension(b('basicConstraints'), True, b('CA:false'))])
|
X509Extension(b('basicConstraints'), True, b('CA:false'))])
|
||||||
# XXX Add get_extensions so the rest of this unit test can be written.
|
exts = request.get_extensions()
|
||||||
|
self.assertEqual(len(exts), 1)
|
||||||
|
self.assertEqual(exts[0].get_short_name(), b('basicConstraints'))
|
||||||
|
self.assertEqual(exts[0].get_critical(), 1)
|
||||||
|
self.assertEqual(exts[0].get_data(), b('0\x00'))
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_extensions(self):
|
||||||
|
"""
|
||||||
|
:py:obj:`X509Req.get_extensions` returns a :py:obj:`list` of
|
||||||
|
extensions added to this X509 request.
|
||||||
|
"""
|
||||||
|
request = X509Req()
|
||||||
|
exts = request.get_extensions()
|
||||||
|
self.assertEqual(exts, [])
|
||||||
|
request.add_extensions([
|
||||||
|
X509Extension(b('basicConstraints'), True, b('CA:true')),
|
||||||
|
X509Extension(b('keyUsage'), False, b('digitalSignature'))])
|
||||||
|
exts = request.get_extensions()
|
||||||
|
self.assertEqual(len(exts), 2)
|
||||||
|
self.assertEqual(exts[0].get_short_name(), b('basicConstraints'))
|
||||||
|
self.assertEqual(exts[0].get_critical(), 1)
|
||||||
|
self.assertEqual(exts[0].get_data(), b('0\x03\x01\x01\xff'))
|
||||||
|
self.assertEqual(exts[1].get_short_name(), b('keyUsage'))
|
||||||
|
self.assertEqual(exts[1].get_critical(), 0)
|
||||||
|
self.assertEqual(exts[1].get_data(), b('\x03\x02\x07\x80'))
|
||||||
|
|
||||||
|
|
||||||
def test_add_extensions_wrong_args(self):
|
def test_add_extensions_wrong_args(self):
|
||||||
|
@ -1163,7 +1286,7 @@ class X509ReqTests(TestCase, _PKeyInteractionTestsMixin):
|
||||||
def test_verify_success(self):
|
def test_verify_success(self):
|
||||||
"""
|
"""
|
||||||
:py:obj:`X509Req.verify` returns :py:obj:`True` if called with a
|
:py:obj:`X509Req.verify` returns :py:obj:`True` if called with a
|
||||||
:py:obj:`OpenSSL.crypto.PKey` which represents the public part ofthe key
|
:py:obj:`OpenSSL.crypto.PKey` which represents the public part of the key
|
||||||
which signed the request.
|
which signed the request.
|
||||||
"""
|
"""
|
||||||
request = X509Req()
|
request = X509Req()
|
||||||
|
@ -1915,6 +2038,21 @@ class PKCS12Tests(TestCase):
|
||||||
self.assertEqual(recovered_cert[-len(ca):], ca)
|
self.assertEqual(recovered_cert[-len(ca):], ca)
|
||||||
|
|
||||||
|
|
||||||
|
def verify_pkcs12_container(self, p12):
|
||||||
|
"""
|
||||||
|
Verify that the PKCS#12 container contains the correct client
|
||||||
|
certificate and private key.
|
||||||
|
|
||||||
|
:param p12: The PKCS12 instance to verify.
|
||||||
|
:type p12: :py:class:`PKCS12`
|
||||||
|
"""
|
||||||
|
cert_pem = dump_certificate(FILETYPE_PEM, p12.get_certificate())
|
||||||
|
key_pem = dump_privatekey(FILETYPE_PEM, p12.get_privatekey())
|
||||||
|
self.assertEqual(
|
||||||
|
(client_cert_pem, client_key_pem, None),
|
||||||
|
(cert_pem, key_pem, p12.get_ca_certificates()))
|
||||||
|
|
||||||
|
|
||||||
def test_load_pkcs12(self):
|
def test_load_pkcs12(self):
|
||||||
"""
|
"""
|
||||||
A PKCS12 string generated using the openssl command line can be loaded
|
A PKCS12 string generated using the openssl command line can be loaded
|
||||||
|
@ -1924,14 +2062,95 @@ class PKCS12Tests(TestCase):
|
||||||
pem = client_key_pem + client_cert_pem
|
pem = client_key_pem + client_cert_pem
|
||||||
p12_str = _runopenssl(
|
p12_str = _runopenssl(
|
||||||
pem, b"pkcs12", b"-export", b"-clcerts", b"-passout", b"pass:" + passwd)
|
pem, b"pkcs12", b"-export", b"-clcerts", b"-passout", b"pass:" + passwd)
|
||||||
p12 = load_pkcs12(p12_str, passwd)
|
p12 = load_pkcs12(p12_str, passphrase=passwd)
|
||||||
# verify
|
self.verify_pkcs12_container(p12)
|
||||||
self.assertTrue(isinstance(p12, PKCS12))
|
|
||||||
cert_pem = dump_certificate(FILETYPE_PEM, p12.get_certificate())
|
|
||||||
self.assertEqual(cert_pem, client_cert_pem)
|
def test_load_pkcs12_text_passphrase(self):
|
||||||
key_pem = dump_privatekey(FILETYPE_PEM, p12.get_privatekey())
|
"""
|
||||||
self.assertEqual(key_pem, client_key_pem)
|
A PKCS12 string generated using the openssl command line can be loaded
|
||||||
self.assertEqual(None, p12.get_ca_certificates())
|
with :py:obj:`load_pkcs12` and its components extracted and examined.
|
||||||
|
Using text as passphrase instead of bytes. DeprecationWarning expected.
|
||||||
|
"""
|
||||||
|
pem = client_key_pem + client_cert_pem
|
||||||
|
passwd = b"whatever"
|
||||||
|
p12_str = _runopenssl(pem, b"pkcs12", b"-export", b"-clcerts",
|
||||||
|
b"-passout", b"pass:" + passwd)
|
||||||
|
with catch_warnings(record=True) as w:
|
||||||
|
simplefilter("always")
|
||||||
|
p12 = load_pkcs12(p12_str, passphrase=b"whatever".decode("ascii"))
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
"{0} for passphrase is no longer accepted, use bytes".format(
|
||||||
|
WARNING_TYPE_EXPECTED
|
||||||
|
),
|
||||||
|
str(w[-1].message)
|
||||||
|
)
|
||||||
|
self.assertIs(w[-1].category, DeprecationWarning)
|
||||||
|
|
||||||
|
self.verify_pkcs12_container(p12)
|
||||||
|
|
||||||
|
|
||||||
|
def test_load_pkcs12_no_passphrase(self):
|
||||||
|
"""
|
||||||
|
A PKCS12 string generated using openssl command line can be loaded with
|
||||||
|
:py:obj:`load_pkcs12` without a passphrase and its components extracted
|
||||||
|
and examined.
|
||||||
|
"""
|
||||||
|
pem = client_key_pem + client_cert_pem
|
||||||
|
p12_str = _runopenssl(
|
||||||
|
pem, b"pkcs12", b"-export", b"-clcerts", b"-passout", b"pass:")
|
||||||
|
p12 = load_pkcs12(p12_str)
|
||||||
|
self.verify_pkcs12_container(p12)
|
||||||
|
|
||||||
|
|
||||||
|
def _dump_and_load(self, dump_passphrase, load_passphrase):
|
||||||
|
"""
|
||||||
|
A helper method to dump and load a PKCS12 object.
|
||||||
|
"""
|
||||||
|
p12 = self.gen_pkcs12(client_cert_pem, client_key_pem)
|
||||||
|
dumped_p12 = p12.export(passphrase=dump_passphrase, iter=2, maciter=3)
|
||||||
|
return load_pkcs12(dumped_p12, passphrase=load_passphrase)
|
||||||
|
|
||||||
|
|
||||||
|
def test_load_pkcs12_null_passphrase_load_empty(self):
|
||||||
|
"""
|
||||||
|
A PKCS12 string can be dumped with a null passphrase, loaded with an
|
||||||
|
empty passphrase with :py:obj:`load_pkcs12`, and its components
|
||||||
|
extracted and examined.
|
||||||
|
"""
|
||||||
|
self.verify_pkcs12_container(
|
||||||
|
self._dump_and_load(dump_passphrase=None, load_passphrase=b''))
|
||||||
|
|
||||||
|
|
||||||
|
def test_load_pkcs12_null_passphrase_load_null(self):
|
||||||
|
"""
|
||||||
|
A PKCS12 string can be dumped with a null passphrase, loaded with a
|
||||||
|
null passphrase with :py:obj:`load_pkcs12`, and its components
|
||||||
|
extracted and examined.
|
||||||
|
"""
|
||||||
|
self.verify_pkcs12_container(
|
||||||
|
self._dump_and_load(dump_passphrase=None, load_passphrase=None))
|
||||||
|
|
||||||
|
|
||||||
|
def test_load_pkcs12_empty_passphrase_load_empty(self):
|
||||||
|
"""
|
||||||
|
A PKCS12 string can be dumped with an empty passphrase, loaded with an
|
||||||
|
empty passphrase with :py:obj:`load_pkcs12`, and its components
|
||||||
|
extracted and examined.
|
||||||
|
"""
|
||||||
|
self.verify_pkcs12_container(
|
||||||
|
self._dump_and_load(dump_passphrase=b'', load_passphrase=b''))
|
||||||
|
|
||||||
|
|
||||||
|
def test_load_pkcs12_empty_passphrase_load_null(self):
|
||||||
|
"""
|
||||||
|
A PKCS12 string can be dumped with an empty passphrase, loaded with a
|
||||||
|
null passphrase with :py:obj:`load_pkcs12`, and its components
|
||||||
|
extracted and examined.
|
||||||
|
"""
|
||||||
|
self.verify_pkcs12_container(
|
||||||
|
self._dump_and_load(dump_passphrase=b'', load_passphrase=None))
|
||||||
|
|
||||||
|
|
||||||
def test_load_pkcs12_garbage(self):
|
def test_load_pkcs12_garbage(self):
|
||||||
|
@ -2073,6 +2292,26 @@ class PKCS12Tests(TestCase):
|
||||||
dumped_p12, key=server_key_pem, cert=server_cert_pem, passwd=b"")
|
dumped_p12, key=server_key_pem, cert=server_cert_pem, passwd=b"")
|
||||||
|
|
||||||
|
|
||||||
|
def test_export_without_bytes(self):
|
||||||
|
"""
|
||||||
|
Test :py:obj:`PKCS12.export` with text not bytes as passphrase
|
||||||
|
"""
|
||||||
|
p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
|
||||||
|
|
||||||
|
with catch_warnings(record=True) as w:
|
||||||
|
simplefilter("always")
|
||||||
|
dumped_p12 = p12.export(passphrase=b"randomtext".decode("ascii"))
|
||||||
|
self.assertEqual(
|
||||||
|
"{0} for passphrase is no longer accepted, use bytes".format(
|
||||||
|
WARNING_TYPE_EXPECTED
|
||||||
|
),
|
||||||
|
str(w[-1].message)
|
||||||
|
)
|
||||||
|
self.assertIs(w[-1].category, DeprecationWarning)
|
||||||
|
self.check_recovery(
|
||||||
|
dumped_p12, key=server_key_pem, cert=server_cert_pem, passwd=b"randomtext")
|
||||||
|
|
||||||
|
|
||||||
def test_key_cert_mismatch(self):
|
def test_key_cert_mismatch(self):
|
||||||
"""
|
"""
|
||||||
:py:obj:`PKCS12.export` raises an exception when a key and certificate
|
:py:obj:`PKCS12.export` raises an exception when a key and certificate
|
||||||
|
@ -2463,7 +2702,7 @@ class FunctionTests(TestCase):
|
||||||
dump_privatekey, FILETYPE_PEM, key, GOOD_CIPHER, cb)
|
dump_privatekey, FILETYPE_PEM, key, GOOD_CIPHER, cb)
|
||||||
|
|
||||||
|
|
||||||
def test_load_pkcs7_data(self):
|
def test_load_pkcs7_data_pem(self):
|
||||||
"""
|
"""
|
||||||
:py:obj:`load_pkcs7_data` accepts a PKCS#7 string and returns an instance of
|
:py:obj:`load_pkcs7_data` accepts a PKCS#7 string and returns an instance of
|
||||||
:py:obj:`PKCS7Type`.
|
:py:obj:`PKCS7Type`.
|
||||||
|
@ -2472,6 +2711,15 @@ class FunctionTests(TestCase):
|
||||||
self.assertTrue(isinstance(pkcs7, PKCS7Type))
|
self.assertTrue(isinstance(pkcs7, PKCS7Type))
|
||||||
|
|
||||||
|
|
||||||
|
def test_load_pkcs7_data_asn1(self):
|
||||||
|
"""
|
||||||
|
:py:obj:`load_pkcs7_data` accepts a bytes containing ASN1 data
|
||||||
|
representing PKCS#7 and returns an instance of :py:obj`PKCS7Type`.
|
||||||
|
"""
|
||||||
|
pkcs7 = load_pkcs7_data(FILETYPE_ASN1, pkcs7DataASN1)
|
||||||
|
self.assertTrue(isinstance(pkcs7, PKCS7Type))
|
||||||
|
|
||||||
|
|
||||||
def test_load_pkcs7_data_invalid(self):
|
def test_load_pkcs7_data_invalid(self):
|
||||||
"""
|
"""
|
||||||
If the data passed to :py:obj:`load_pkcs7_data` is invalid,
|
If the data passed to :py:obj:`load_pkcs7_data` is invalid,
|
||||||
|
@ -2796,11 +3044,9 @@ class CRLTests(TestCase):
|
||||||
self.assertRaises(TypeError, CRL, None)
|
self.assertRaises(TypeError, CRL, None)
|
||||||
|
|
||||||
|
|
||||||
def test_export(self):
|
def _get_crl(self):
|
||||||
"""
|
"""
|
||||||
Use python to create a simple CRL with a revocation, and export
|
Get a new ``CRL`` with a revocation.
|
||||||
the CRL in formats of PEM, DER and text. Those outputs are verified
|
|
||||||
with the openssl program.
|
|
||||||
"""
|
"""
|
||||||
crl = CRL()
|
crl = CRL()
|
||||||
revoked = Revoked()
|
revoked = Revoked()
|
||||||
|
@ -2809,26 +3055,110 @@ class CRLTests(TestCase):
|
||||||
revoked.set_serial(b('3ab'))
|
revoked.set_serial(b('3ab'))
|
||||||
revoked.set_reason(b('sUpErSeDEd'))
|
revoked.set_reason(b('sUpErSeDEd'))
|
||||||
crl.add_revoked(revoked)
|
crl.add_revoked(revoked)
|
||||||
|
return crl
|
||||||
|
|
||||||
|
|
||||||
|
def test_export_pem(self):
|
||||||
|
"""
|
||||||
|
If not passed a format, ``CRL.export`` returns a "PEM" format string
|
||||||
|
representing a serial number, a revoked reason, and certificate issuer
|
||||||
|
information.
|
||||||
|
"""
|
||||||
|
crl = self._get_crl()
|
||||||
# PEM format
|
# PEM format
|
||||||
dumped_crl = crl.export(self.cert, self.pkey, days=20)
|
dumped_crl = crl.export(self.cert, self.pkey, days=20)
|
||||||
text = _runopenssl(dumped_crl, b"crl", b"-noout", b"-text")
|
text = _runopenssl(dumped_crl, b"crl", b"-noout", b"-text")
|
||||||
|
|
||||||
|
# These magic values are based on the way the CRL above was constructed
|
||||||
|
# and with what certificate it was exported.
|
||||||
text.index(b('Serial Number: 03AB'))
|
text.index(b('Serial Number: 03AB'))
|
||||||
text.index(b('Superseded'))
|
text.index(b('Superseded'))
|
||||||
text.index(b('Issuer: /C=US/ST=IL/L=Chicago/O=Testing/CN=Testing Root CA'))
|
text.index(
|
||||||
|
b('Issuer: /C=US/ST=IL/L=Chicago/O=Testing/CN=Testing Root CA')
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_export_der(self):
|
||||||
|
"""
|
||||||
|
If passed ``FILETYPE_ASN1`` for the format, ``CRL.export`` returns a
|
||||||
|
"DER" format string representing a serial number, a revoked reason, and
|
||||||
|
certificate issuer information.
|
||||||
|
"""
|
||||||
|
crl = self._get_crl()
|
||||||
|
|
||||||
# DER format
|
# DER format
|
||||||
dumped_crl = crl.export(self.cert, self.pkey, FILETYPE_ASN1)
|
dumped_crl = crl.export(self.cert, self.pkey, FILETYPE_ASN1)
|
||||||
text = _runopenssl(dumped_crl, b"crl", b"-noout", b"-text", b"-inform", b"DER")
|
text = _runopenssl(
|
||||||
|
dumped_crl, b"crl", b"-noout", b"-text", b"-inform", b"DER"
|
||||||
|
)
|
||||||
text.index(b('Serial Number: 03AB'))
|
text.index(b('Serial Number: 03AB'))
|
||||||
text.index(b('Superseded'))
|
text.index(b('Superseded'))
|
||||||
text.index(b('Issuer: /C=US/ST=IL/L=Chicago/O=Testing/CN=Testing Root CA'))
|
text.index(
|
||||||
|
b('Issuer: /C=US/ST=IL/L=Chicago/O=Testing/CN=Testing Root CA')
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_export_text(self):
|
||||||
|
"""
|
||||||
|
If passed ``FILETYPE_TEXT`` for the format, ``CRL.export`` returns a
|
||||||
|
text format string like the one produced by the openssl command line
|
||||||
|
tool.
|
||||||
|
"""
|
||||||
|
crl = self._get_crl()
|
||||||
|
|
||||||
|
dumped_crl = crl.export(self.cert, self.pkey, FILETYPE_ASN1)
|
||||||
|
text = _runopenssl(
|
||||||
|
dumped_crl, b"crl", b"-noout", b"-text", b"-inform", b"DER"
|
||||||
|
)
|
||||||
|
|
||||||
# text format
|
# text format
|
||||||
dumped_text = crl.export(self.cert, self.pkey, type=FILETYPE_TEXT)
|
dumped_text = crl.export(self.cert, self.pkey, type=FILETYPE_TEXT)
|
||||||
self.assertEqual(text, dumped_text)
|
self.assertEqual(text, dumped_text)
|
||||||
|
|
||||||
|
|
||||||
|
def test_export_custom_digest(self):
|
||||||
|
"""
|
||||||
|
If passed the name of a digest function, ``CRL.export`` uses a
|
||||||
|
signature algorithm based on that digest function.
|
||||||
|
"""
|
||||||
|
crl = self._get_crl()
|
||||||
|
dumped_crl = crl.export(self.cert, self.pkey, digest=b"sha1")
|
||||||
|
text = _runopenssl(dumped_crl, b"crl", b"-noout", b"-text")
|
||||||
|
text.index(b('Signature Algorithm: sha1'))
|
||||||
|
|
||||||
|
|
||||||
|
def test_export_md5_digest(self):
|
||||||
|
"""
|
||||||
|
If passed md5 as the digest function, ``CRL.export`` uses md5 and does
|
||||||
|
not emit a deprecation warning.
|
||||||
|
"""
|
||||||
|
crl = self._get_crl()
|
||||||
|
with catch_warnings(record=True) as catcher:
|
||||||
|
simplefilter("always")
|
||||||
|
self.assertEqual(0, len(catcher))
|
||||||
|
dumped_crl = crl.export(self.cert, self.pkey, digest=b"md5")
|
||||||
|
text = _runopenssl(dumped_crl, b"crl", b"-noout", b"-text")
|
||||||
|
text.index(b('Signature Algorithm: md5'))
|
||||||
|
|
||||||
|
|
||||||
|
def test_export_default_digest(self):
|
||||||
|
"""
|
||||||
|
If not passed the name of a digest function, ``CRL.export`` uses a
|
||||||
|
signature algorithm based on MD5 and emits a deprecation warning.
|
||||||
|
"""
|
||||||
|
crl = self._get_crl()
|
||||||
|
with catch_warnings(record=True) as catcher:
|
||||||
|
simplefilter("always")
|
||||||
|
dumped_crl = crl.export(self.cert, self.pkey)
|
||||||
|
self.assertEqual(
|
||||||
|
"The default message digest (md5) is deprecated. "
|
||||||
|
"Pass the name of a message digest explicitly.",
|
||||||
|
str(catcher[0].message),
|
||||||
|
)
|
||||||
|
text = _runopenssl(dumped_crl, b"crl", b"-noout", b"-text")
|
||||||
|
text.index(b('Signature Algorithm: md5'))
|
||||||
|
|
||||||
|
|
||||||
def test_export_invalid(self):
|
def test_export_invalid(self):
|
||||||
"""
|
"""
|
||||||
If :py:obj:`CRL.export` is used with an uninitialized :py:obj:`X509`
|
If :py:obj:`CRL.export` is used with an uninitialized :py:obj:`X509`
|
||||||
|
@ -2859,7 +3189,7 @@ class CRLTests(TestCase):
|
||||||
crl = CRL()
|
crl = CRL()
|
||||||
self.assertRaises(TypeError, crl.export)
|
self.assertRaises(TypeError, crl.export)
|
||||||
self.assertRaises(TypeError, crl.export, self.cert)
|
self.assertRaises(TypeError, crl.export, self.cert)
|
||||||
self.assertRaises(TypeError, crl.export, self.cert, self.pkey, FILETYPE_PEM, 10, "foo")
|
self.assertRaises(TypeError, crl.export, self.cert, self.pkey, FILETYPE_PEM, 10, "md5", "foo")
|
||||||
|
|
||||||
self.assertRaises(TypeError, crl.export, None, self.pkey, FILETYPE_PEM, 10)
|
self.assertRaises(TypeError, crl.export, None, self.pkey, FILETYPE_PEM, 10)
|
||||||
self.assertRaises(TypeError, crl.export, self.cert, None, FILETYPE_PEM, 10)
|
self.assertRaises(TypeError, crl.export, self.cert, None, FILETYPE_PEM, 10)
|
||||||
|
@ -2877,6 +3207,19 @@ class CRLTests(TestCase):
|
||||||
self.assertRaises(ValueError, crl.export, self.cert, self.pkey, 100, 10)
|
self.assertRaises(ValueError, crl.export, self.cert, self.pkey, 100, 10)
|
||||||
|
|
||||||
|
|
||||||
|
def test_export_unknown_digest(self):
|
||||||
|
"""
|
||||||
|
Calling :py:obj:`OpenSSL.CRL.export` with a unsupported digest results
|
||||||
|
in a :py:obj:`ValueError` being raised.
|
||||||
|
"""
|
||||||
|
crl = CRL()
|
||||||
|
self.assertRaises(
|
||||||
|
ValueError,
|
||||||
|
crl.export,
|
||||||
|
self.cert, self.pkey, FILETYPE_PEM, 10, b"strange-digest"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_get_revoked(self):
|
def test_get_revoked(self):
|
||||||
"""
|
"""
|
||||||
Use python to create a simple CRL with two revocations.
|
Use python to create a simple CRL with two revocations.
|
||||||
|
@ -2977,6 +3320,107 @@ class CRLTests(TestCase):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class X509StoreContextTests(TestCase):
|
||||||
|
"""
|
||||||
|
Tests for :py:obj:`OpenSSL.crypto.X509StoreContext`.
|
||||||
|
"""
|
||||||
|
root_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
|
||||||
|
intermediate_cert = load_certificate(FILETYPE_PEM, intermediate_cert_pem)
|
||||||
|
intermediate_server_cert = load_certificate(FILETYPE_PEM, intermediate_server_cert_pem)
|
||||||
|
|
||||||
|
def test_valid(self):
|
||||||
|
"""
|
||||||
|
:py:obj:`verify_certificate` returns ``None`` when called with a certificate
|
||||||
|
and valid chain.
|
||||||
|
"""
|
||||||
|
store = X509Store()
|
||||||
|
store.add_cert(self.root_cert)
|
||||||
|
store.add_cert(self.intermediate_cert)
|
||||||
|
store_ctx = X509StoreContext(store, self.intermediate_server_cert)
|
||||||
|
self.assertEqual(store_ctx.verify_certificate(), None)
|
||||||
|
|
||||||
|
|
||||||
|
def test_reuse(self):
|
||||||
|
"""
|
||||||
|
:py:obj:`verify_certificate` can be called multiple times with the same
|
||||||
|
``X509StoreContext`` instance to produce the same result.
|
||||||
|
"""
|
||||||
|
store = X509Store()
|
||||||
|
store.add_cert(self.root_cert)
|
||||||
|
store.add_cert(self.intermediate_cert)
|
||||||
|
store_ctx = X509StoreContext(store, self.intermediate_server_cert)
|
||||||
|
self.assertEqual(store_ctx.verify_certificate(), None)
|
||||||
|
self.assertEqual(store_ctx.verify_certificate(), None)
|
||||||
|
|
||||||
|
|
||||||
|
def test_trusted_self_signed(self):
|
||||||
|
"""
|
||||||
|
:py:obj:`verify_certificate` returns ``None`` when called with a self-signed
|
||||||
|
certificate and itself in the chain.
|
||||||
|
"""
|
||||||
|
store = X509Store()
|
||||||
|
store.add_cert(self.root_cert)
|
||||||
|
store_ctx = X509StoreContext(store, self.root_cert)
|
||||||
|
self.assertEqual(store_ctx.verify_certificate(), None)
|
||||||
|
|
||||||
|
|
||||||
|
def test_untrusted_self_signed(self):
|
||||||
|
"""
|
||||||
|
:py:obj:`verify_certificate` raises error when a self-signed certificate is
|
||||||
|
verified without itself in the chain.
|
||||||
|
"""
|
||||||
|
store = X509Store()
|
||||||
|
store_ctx = X509StoreContext(store, self.root_cert)
|
||||||
|
e = self.assertRaises(X509StoreContextError, store_ctx.verify_certificate)
|
||||||
|
self.assertEqual(e.args[0][2], 'self signed certificate')
|
||||||
|
self.assertEqual(e.certificate.get_subject().CN, 'Testing Root CA')
|
||||||
|
|
||||||
|
|
||||||
|
def test_invalid_chain_no_root(self):
|
||||||
|
"""
|
||||||
|
:py:obj:`verify_certificate` raises error when a root certificate is missing
|
||||||
|
from the chain.
|
||||||
|
"""
|
||||||
|
store = X509Store()
|
||||||
|
store.add_cert(self.intermediate_cert)
|
||||||
|
store_ctx = X509StoreContext(store, self.intermediate_server_cert)
|
||||||
|
e = self.assertRaises(X509StoreContextError, store_ctx.verify_certificate)
|
||||||
|
self.assertEqual(e.args[0][2], 'unable to get issuer certificate')
|
||||||
|
self.assertEqual(e.certificate.get_subject().CN, 'intermediate')
|
||||||
|
|
||||||
|
|
||||||
|
def test_invalid_chain_no_intermediate(self):
|
||||||
|
"""
|
||||||
|
:py:obj:`verify_certificate` raises error when an intermediate certificate is
|
||||||
|
missing from the chain.
|
||||||
|
"""
|
||||||
|
store = X509Store()
|
||||||
|
store.add_cert(self.root_cert)
|
||||||
|
store_ctx = X509StoreContext(store, self.intermediate_server_cert)
|
||||||
|
e = self.assertRaises(X509StoreContextError, store_ctx.verify_certificate)
|
||||||
|
self.assertEqual(e.args[0][2], 'unable to get local issuer certificate')
|
||||||
|
self.assertEqual(e.certificate.get_subject().CN, 'intermediate-service')
|
||||||
|
|
||||||
|
|
||||||
|
def test_modification_pre_verify(self):
|
||||||
|
"""
|
||||||
|
:py:obj:`verify_certificate` can use a store context modified after
|
||||||
|
instantiation.
|
||||||
|
"""
|
||||||
|
store_bad = X509Store()
|
||||||
|
store_bad.add_cert(self.intermediate_cert)
|
||||||
|
store_good = X509Store()
|
||||||
|
store_good.add_cert(self.root_cert)
|
||||||
|
store_good.add_cert(self.intermediate_cert)
|
||||||
|
store_ctx = X509StoreContext(store_bad, self.intermediate_server_cert)
|
||||||
|
e = self.assertRaises(X509StoreContextError, store_ctx.verify_certificate)
|
||||||
|
self.assertEqual(e.args[0][2], 'unable to get issuer certificate')
|
||||||
|
self.assertEqual(e.certificate.get_subject().CN, 'intermediate')
|
||||||
|
store_ctx.set_store(store_good)
|
||||||
|
self.assertEqual(store_ctx.verify_certificate(), None)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class SignVerifyTests(TestCase):
|
class SignVerifyTests(TestCase):
|
||||||
"""
|
"""
|
||||||
Tests for :py:obj:`OpenSSL.crypto.sign` and :py:obj:`OpenSSL.crypto.verify`.
|
Tests for :py:obj:`OpenSSL.crypto.sign` and :py:obj:`OpenSSL.crypto.verify`.
|
||||||
|
@ -3022,6 +3466,47 @@ class SignVerifyTests(TestCase):
|
||||||
ValueError, verify, good_cert, sig, content, "strange-digest")
|
ValueError, verify, good_cert, sig, content, "strange-digest")
|
||||||
|
|
||||||
|
|
||||||
|
def test_sign_verify_with_text(self):
|
||||||
|
"""
|
||||||
|
:py:obj:`sign` generates a cryptographic signature which :py:obj:`verify` can check.
|
||||||
|
Deprecation warnings raised because using text instead of bytes as content
|
||||||
|
"""
|
||||||
|
content = (
|
||||||
|
b"It was a bright cold day in April, and the clocks were striking "
|
||||||
|
b"thirteen. Winston Smith, his chin nuzzled into his breast in an "
|
||||||
|
b"effort to escape the vile wind, slipped quickly through the "
|
||||||
|
b"glass doors of Victory Mansions, though not quickly enough to "
|
||||||
|
b"prevent a swirl of gritty dust from entering along with him."
|
||||||
|
).decode("ascii")
|
||||||
|
|
||||||
|
priv_key = load_privatekey(FILETYPE_PEM, root_key_pem)
|
||||||
|
cert = load_certificate(FILETYPE_PEM, root_cert_pem)
|
||||||
|
for digest in ['md5', 'sha1']:
|
||||||
|
with catch_warnings(record=True) as w:
|
||||||
|
simplefilter("always")
|
||||||
|
sig = sign(priv_key, content, digest)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
"{0} for data is no longer accepted, use bytes".format(
|
||||||
|
WARNING_TYPE_EXPECTED
|
||||||
|
),
|
||||||
|
str(w[-1].message)
|
||||||
|
)
|
||||||
|
self.assertIs(w[-1].category, DeprecationWarning)
|
||||||
|
|
||||||
|
with catch_warnings(record=True) as w:
|
||||||
|
simplefilter("always")
|
||||||
|
verify(cert, sig, content, digest)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
"{0} for data is no longer accepted, use bytes".format(
|
||||||
|
WARNING_TYPE_EXPECTED
|
||||||
|
),
|
||||||
|
str(w[-1].message)
|
||||||
|
)
|
||||||
|
self.assertIs(w[-1].category, DeprecationWarning)
|
||||||
|
|
||||||
|
|
||||||
def test_sign_nulls(self):
|
def test_sign_nulls(self):
|
||||||
"""
|
"""
|
||||||
:py:obj:`sign` produces a signature for a string with embedded nulls.
|
:py:obj:`sign` produces a signature for a string with embedded nulls.
|
||||||
|
@ -3033,5 +3518,154 @@ class SignVerifyTests(TestCase):
|
||||||
verify(good_cert, sig, content, "sha1")
|
verify(good_cert, sig, content, "sha1")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class EllipticCurveTests(TestCase):
|
||||||
|
"""
|
||||||
|
Tests for :py:class:`_EllipticCurve`, :py:obj:`get_elliptic_curve`, and
|
||||||
|
:py:obj:`get_elliptic_curves`.
|
||||||
|
"""
|
||||||
|
def test_set(self):
|
||||||
|
"""
|
||||||
|
:py:obj:`get_elliptic_curves` returns a :py:obj:`set`.
|
||||||
|
"""
|
||||||
|
self.assertIsInstance(get_elliptic_curves(), set)
|
||||||
|
|
||||||
|
|
||||||
|
def test_some_curves(self):
|
||||||
|
"""
|
||||||
|
If :py:mod:`cryptography` has elliptic curve support then the set
|
||||||
|
returned by :py:obj:`get_elliptic_curves` has some elliptic curves in
|
||||||
|
it.
|
||||||
|
|
||||||
|
There could be an OpenSSL that violates this assumption. If so, this
|
||||||
|
test will fail and we'll find out.
|
||||||
|
"""
|
||||||
|
curves = get_elliptic_curves()
|
||||||
|
if lib.Cryptography_HAS_EC:
|
||||||
|
self.assertTrue(curves)
|
||||||
|
else:
|
||||||
|
self.assertFalse(curves)
|
||||||
|
|
||||||
|
|
||||||
|
def test_a_curve(self):
|
||||||
|
"""
|
||||||
|
:py:obj:`get_elliptic_curve` can be used to retrieve a particular
|
||||||
|
supported curve.
|
||||||
|
"""
|
||||||
|
curves = get_elliptic_curves()
|
||||||
|
if curves:
|
||||||
|
curve = next(iter(curves))
|
||||||
|
self.assertEqual(curve.name, get_elliptic_curve(curve.name).name)
|
||||||
|
else:
|
||||||
|
self.assertRaises(ValueError, get_elliptic_curve, u("prime256v1"))
|
||||||
|
|
||||||
|
|
||||||
|
def test_not_a_curve(self):
|
||||||
|
"""
|
||||||
|
:py:obj:`get_elliptic_curve` raises :py:class:`ValueError` if called
|
||||||
|
with a name which does not identify a supported curve.
|
||||||
|
"""
|
||||||
|
self.assertRaises(
|
||||||
|
ValueError, get_elliptic_curve, u("this curve was just invented"))
|
||||||
|
|
||||||
|
|
||||||
|
def test_repr(self):
|
||||||
|
"""
|
||||||
|
The string representation of a curve object includes simply states the
|
||||||
|
object is a curve and what its name is.
|
||||||
|
"""
|
||||||
|
curves = get_elliptic_curves()
|
||||||
|
if curves:
|
||||||
|
curve = next(iter(curves))
|
||||||
|
self.assertEqual("<Curve %r>" % (curve.name,), repr(curve))
|
||||||
|
|
||||||
|
|
||||||
|
def test_to_EC_KEY(self):
|
||||||
|
"""
|
||||||
|
The curve object can export a version of itself as an EC_KEY* via the
|
||||||
|
private :py:meth:`_EllipticCurve._to_EC_KEY`.
|
||||||
|
"""
|
||||||
|
curves = get_elliptic_curves()
|
||||||
|
if curves:
|
||||||
|
curve = next(iter(curves))
|
||||||
|
# It's not easy to assert anything about this object. However, see
|
||||||
|
# leakcheck/crypto.py for a test that demonstrates it at least does
|
||||||
|
# not leak memory.
|
||||||
|
curve._to_EC_KEY()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class EllipticCurveFactory(object):
|
||||||
|
"""
|
||||||
|
A helper to get the names of two curves.
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
|
curves = iter(get_elliptic_curves())
|
||||||
|
try:
|
||||||
|
self.curve_name = next(curves).name
|
||||||
|
self.another_curve_name = next(curves).name
|
||||||
|
except StopIteration:
|
||||||
|
self.curve_name = self.another_curve_name = None
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class EllipticCurveEqualityTests(TestCase, EqualityTestsMixin):
|
||||||
|
"""
|
||||||
|
Tests :py:type:`_EllipticCurve`\ 's implementation of ``==`` and ``!=``.
|
||||||
|
"""
|
||||||
|
curve_factory = EllipticCurveFactory()
|
||||||
|
|
||||||
|
if curve_factory.curve_name is None:
|
||||||
|
skip = "There are no curves available there can be no curve objects."
|
||||||
|
|
||||||
|
|
||||||
|
def anInstance(self):
|
||||||
|
"""
|
||||||
|
Get the curve object for an arbitrary curve supported by the system.
|
||||||
|
"""
|
||||||
|
return get_elliptic_curve(self.curve_factory.curve_name)
|
||||||
|
|
||||||
|
|
||||||
|
def anotherInstance(self):
|
||||||
|
"""
|
||||||
|
Get the curve object for an arbitrary curve supported by the system -
|
||||||
|
but not the one returned by C{anInstance}.
|
||||||
|
"""
|
||||||
|
return get_elliptic_curve(self.curve_factory.another_curve_name)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class EllipticCurveHashTests(TestCase):
|
||||||
|
"""
|
||||||
|
Tests for :py:type:`_EllipticCurve`\ 's implementation of hashing (thus use
|
||||||
|
as an item in a :py:type:`dict` or :py:type:`set`).
|
||||||
|
"""
|
||||||
|
curve_factory = EllipticCurveFactory()
|
||||||
|
|
||||||
|
if curve_factory.curve_name is None:
|
||||||
|
skip = "There are no curves available there can be no curve objects."
|
||||||
|
|
||||||
|
|
||||||
|
def test_contains(self):
|
||||||
|
"""
|
||||||
|
The ``in`` operator reports that a :py:type:`set` containing a curve
|
||||||
|
does contain that curve.
|
||||||
|
"""
|
||||||
|
curve = get_elliptic_curve(self.curve_factory.curve_name)
|
||||||
|
curves = set([curve])
|
||||||
|
self.assertIn(curve, curves)
|
||||||
|
|
||||||
|
|
||||||
|
def test_does_not_contain(self):
|
||||||
|
"""
|
||||||
|
The ``in`` operator reports that a :py:type:`set` not containing a
|
||||||
|
curve does not contain that curve.
|
||||||
|
"""
|
||||||
|
curve = get_elliptic_curve(self.curve_factory.curve_name)
|
||||||
|
curves = set([get_elliptic_curve(self.curve_factory.another_curve_name)])
|
||||||
|
self.assertNotIn(curve, curves)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|
|
@ -10,7 +10,7 @@ import os
|
||||||
import stat
|
import stat
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from OpenSSL.test.util import TestCase, b
|
from OpenSSL.test.util import NON_ASCII, TestCase, b
|
||||||
from OpenSSL import rand
|
from OpenSSL import rand
|
||||||
|
|
||||||
|
|
||||||
|
@ -176,27 +176,47 @@ class RandTests(TestCase):
|
||||||
self.assertRaises(TypeError, rand.write_file, None)
|
self.assertRaises(TypeError, rand.write_file, None)
|
||||||
self.assertRaises(TypeError, rand.write_file, "foo", None)
|
self.assertRaises(TypeError, rand.write_file, "foo", None)
|
||||||
|
|
||||||
|
def _read_write_test(self, path):
|
||||||
|
"""
|
||||||
|
Verify that ``rand.write_file`` and ``rand.load_file`` can be used.
|
||||||
|
"""
|
||||||
|
# Create the file so cleanup is more straightforward
|
||||||
|
with open(path, "w"):
|
||||||
|
pass
|
||||||
|
|
||||||
def test_files(self):
|
|
||||||
"""
|
|
||||||
Test reading and writing of files via rand functions.
|
|
||||||
"""
|
|
||||||
# Write random bytes to a file
|
|
||||||
tmpfile = self.mktemp()
|
|
||||||
# Make sure it exists (so cleanup definitely succeeds)
|
|
||||||
fObj = open(tmpfile, 'w')
|
|
||||||
fObj.close()
|
|
||||||
try:
|
try:
|
||||||
rand.write_file(tmpfile)
|
# Write random bytes to a file
|
||||||
|
rand.write_file(path)
|
||||||
|
|
||||||
# Verify length of written file
|
# Verify length of written file
|
||||||
size = os.stat(tmpfile)[stat.ST_SIZE]
|
size = os.stat(path)[stat.ST_SIZE]
|
||||||
self.assertEqual(1024, size)
|
self.assertEqual(1024, size)
|
||||||
|
|
||||||
# Read random bytes from file
|
# Read random bytes from file
|
||||||
rand.load_file(tmpfile)
|
rand.load_file(path)
|
||||||
rand.load_file(tmpfile, 4) # specify a length
|
rand.load_file(path, 4) # specify a length
|
||||||
finally:
|
finally:
|
||||||
# Cleanup
|
# Cleanup
|
||||||
os.unlink(tmpfile)
|
os.unlink(path)
|
||||||
|
|
||||||
|
|
||||||
|
def test_bytes_paths(self):
|
||||||
|
"""
|
||||||
|
Random data can be saved and loaded to files with paths specified as
|
||||||
|
bytes.
|
||||||
|
"""
|
||||||
|
path = self.mktemp()
|
||||||
|
path += NON_ASCII.encode(sys.getfilesystemencoding())
|
||||||
|
self._read_write_test(path)
|
||||||
|
|
||||||
|
|
||||||
|
def test_unicode_paths(self):
|
||||||
|
"""
|
||||||
|
Random data can be saved and loaded to files with paths specified as
|
||||||
|
unicode.
|
||||||
|
"""
|
||||||
|
path = self.mktemp().decode('utf-8') + NON_ASCII
|
||||||
|
self._read_write_test(path)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,24 @@
|
||||||
|
# Copyright (C) Jean-Paul Calderone
|
||||||
|
# See LICENSE for details.
|
||||||
|
|
||||||
|
"""
|
||||||
|
Unit tests for :py:obj:`OpenSSL.tsafe`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from OpenSSL.SSL import TLSv1_METHOD, Context
|
||||||
|
from OpenSSL.tsafe import Connection
|
||||||
|
from OpenSSL.test.util import TestCase
|
||||||
|
|
||||||
|
|
||||||
|
class ConnectionTest(TestCase):
|
||||||
|
"""
|
||||||
|
Tests for :py:obj:`OpenSSL.tsafe.Connection`.
|
||||||
|
"""
|
||||||
|
def test_instantiation(self):
|
||||||
|
"""
|
||||||
|
:py:obj:`OpenSSL.tsafe.Connection` can be instantiated.
|
||||||
|
"""
|
||||||
|
# The following line should not throw an error. This isn't an ideal
|
||||||
|
# test. It would be great to refactor the other Connection tests so
|
||||||
|
# they could automatically be applied to this class too.
|
||||||
|
Connection(Context(TLSv1_METHOD), None)
|
|
@ -0,0 +1,17 @@
|
||||||
|
from OpenSSL._util import exception_from_error_queue, lib
|
||||||
|
from OpenSSL.test.util import TestCase
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class ErrorTests(TestCase):
|
||||||
|
"""
|
||||||
|
Tests for handling of certain OpenSSL error cases.
|
||||||
|
"""
|
||||||
|
def test_exception_from_error_queue_nonexistent_reason(self):
|
||||||
|
"""
|
||||||
|
:py:func:`exception_from_error_queue` raises ``ValueError`` when it
|
||||||
|
encounters an OpenSSL error code which does not have a reason string.
|
||||||
|
"""
|
||||||
|
lib.ERR_put_error(lib.ERR_LIB_EVP, 0, 1112, b"", 10)
|
||||||
|
exc = self.assertRaises(ValueError, exception_from_error_queue, ValueError)
|
||||||
|
self.assertEqual(exc.args[0][0][2], "")
|
|
@ -14,6 +14,8 @@ from tempfile import mktemp
|
||||||
from unittest import TestCase
|
from unittest import TestCase
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
from six import PY3
|
||||||
|
|
||||||
from OpenSSL._util import exception_from_error_queue
|
from OpenSSL._util import exception_from_error_queue
|
||||||
from OpenSSL.crypto import Error
|
from OpenSSL.crypto import Error
|
||||||
|
|
||||||
|
@ -25,6 +27,11 @@ except Exception:
|
||||||
|
|
||||||
from OpenSSL._util import ffi, lib, byte_string as b
|
from OpenSSL._util import ffi, lib, byte_string as b
|
||||||
|
|
||||||
|
|
||||||
|
# This is the UTF-8 encoding of the SNOWMAN unicode code point.
|
||||||
|
NON_ASCII = b("\xe2\x98\x83").decode("utf-8")
|
||||||
|
|
||||||
|
|
||||||
class TestCase(TestCase):
|
class TestCase(TestCase):
|
||||||
"""
|
"""
|
||||||
:py:class:`TestCase` adds useful testing functionality beyond what is available
|
:py:class:`TestCase` adds useful testing functionality beyond what is available
|
||||||
|
@ -210,7 +217,24 @@ class TestCase(TestCase):
|
||||||
return containee
|
return containee
|
||||||
assertIn = failUnlessIn
|
assertIn = failUnlessIn
|
||||||
|
|
||||||
def failUnlessIdentical(self, first, second, msg=None):
|
def assertNotIn(self, containee, container, msg=None):
|
||||||
|
"""
|
||||||
|
Fail the test if C{containee} is found in C{container}.
|
||||||
|
|
||||||
|
@param containee: the value that should not be in C{container}
|
||||||
|
@param container: a sequence type, or in the case of a mapping type,
|
||||||
|
will follow semantics of 'if key in dict.keys()'
|
||||||
|
@param msg: if msg is None, then the failure message will be
|
||||||
|
'%r in %r' % (first, second)
|
||||||
|
"""
|
||||||
|
if containee in container:
|
||||||
|
raise self.failureException(msg or "%r in %r"
|
||||||
|
% (containee, container))
|
||||||
|
return containee
|
||||||
|
failIfIn = assertNotIn
|
||||||
|
|
||||||
|
|
||||||
|
def assertIs(self, first, second, msg=None):
|
||||||
"""
|
"""
|
||||||
Fail the test if :py:data:`first` is not :py:data:`second`. This is an
|
Fail the test if :py:data:`first` is not :py:data:`second`. This is an
|
||||||
obect-identity-equality test, not an object equality
|
obect-identity-equality test, not an object equality
|
||||||
|
@ -222,10 +246,10 @@ class TestCase(TestCase):
|
||||||
if first is not second:
|
if first is not second:
|
||||||
raise self.failureException(msg or '%r is not %r' % (first, second))
|
raise self.failureException(msg or '%r is not %r' % (first, second))
|
||||||
return first
|
return first
|
||||||
assertIdentical = failUnlessIdentical
|
assertIdentical = failUnlessIdentical = assertIs
|
||||||
|
|
||||||
|
|
||||||
def failIfIdentical(self, first, second, msg=None):
|
def assertIsNot(self, first, second, msg=None):
|
||||||
"""
|
"""
|
||||||
Fail the test if :py:data:`first` is :py:data:`second`. This is an
|
Fail the test if :py:data:`first` is :py:data:`second`. This is an
|
||||||
obect-identity-equality test, not an object equality
|
obect-identity-equality test, not an object equality
|
||||||
|
@ -237,7 +261,7 @@ class TestCase(TestCase):
|
||||||
if first is second:
|
if first is second:
|
||||||
raise self.failureException(msg or '%r is %r' % (first, second))
|
raise self.failureException(msg or '%r is %r' % (first, second))
|
||||||
return first
|
return first
|
||||||
assertNotIdentical = failIfIdentical
|
assertNotIdentical = failIfIdentical = assertIsNot
|
||||||
|
|
||||||
|
|
||||||
def failUnlessRaises(self, exception, f, *args, **kwargs):
|
def failUnlessRaises(self, exception, f, *args, **kwargs):
|
||||||
|
@ -300,3 +324,140 @@ class TestCase(TestCase):
|
||||||
self.assertTrue(isinstance(theType, type))
|
self.assertTrue(isinstance(theType, type))
|
||||||
instance = theType(*constructionArgs)
|
instance = theType(*constructionArgs)
|
||||||
self.assertIdentical(type(instance), theType)
|
self.assertIdentical(type(instance), theType)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class EqualityTestsMixin(object):
|
||||||
|
"""
|
||||||
|
A mixin defining tests for the standard implementation of C{==} and C{!=}.
|
||||||
|
"""
|
||||||
|
def anInstance(self):
|
||||||
|
"""
|
||||||
|
Return an instance of the class under test. Each call to this method
|
||||||
|
must return a different object. All objects returned must be equal to
|
||||||
|
each other.
|
||||||
|
"""
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
|
||||||
|
def anotherInstance(self):
|
||||||
|
"""
|
||||||
|
Return an instance of the class under test. Each call to this method
|
||||||
|
must return a different object. The objects must not be equal to the
|
||||||
|
objects returned by C{anInstance}. They may or may not be equal to
|
||||||
|
each other (they will not be compared against each other).
|
||||||
|
"""
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
|
||||||
|
def test_identicalEq(self):
|
||||||
|
"""
|
||||||
|
An object compares equal to itself using the C{==} operator.
|
||||||
|
"""
|
||||||
|
o = self.anInstance()
|
||||||
|
self.assertTrue(o == o)
|
||||||
|
|
||||||
|
|
||||||
|
def test_identicalNe(self):
|
||||||
|
"""
|
||||||
|
An object doesn't compare not equal to itself using the C{!=} operator.
|
||||||
|
"""
|
||||||
|
o = self.anInstance()
|
||||||
|
self.assertFalse(o != o)
|
||||||
|
|
||||||
|
|
||||||
|
def test_sameEq(self):
|
||||||
|
"""
|
||||||
|
Two objects that are equal to each other compare equal to each other
|
||||||
|
using the C{==} operator.
|
||||||
|
"""
|
||||||
|
a = self.anInstance()
|
||||||
|
b = self.anInstance()
|
||||||
|
self.assertTrue(a == b)
|
||||||
|
|
||||||
|
|
||||||
|
def test_sameNe(self):
|
||||||
|
"""
|
||||||
|
Two objects that are equal to each other do not compare not equal to
|
||||||
|
each other using the C{!=} operator.
|
||||||
|
"""
|
||||||
|
a = self.anInstance()
|
||||||
|
b = self.anInstance()
|
||||||
|
self.assertFalse(a != b)
|
||||||
|
|
||||||
|
|
||||||
|
def test_differentEq(self):
|
||||||
|
"""
|
||||||
|
Two objects that are not equal to each other do not compare equal to
|
||||||
|
each other using the C{==} operator.
|
||||||
|
"""
|
||||||
|
a = self.anInstance()
|
||||||
|
b = self.anotherInstance()
|
||||||
|
self.assertFalse(a == b)
|
||||||
|
|
||||||
|
|
||||||
|
def test_differentNe(self):
|
||||||
|
"""
|
||||||
|
Two objects that are not equal to each other compare not equal to each
|
||||||
|
other using the C{!=} operator.
|
||||||
|
"""
|
||||||
|
a = self.anInstance()
|
||||||
|
b = self.anotherInstance()
|
||||||
|
self.assertTrue(a != b)
|
||||||
|
|
||||||
|
|
||||||
|
def test_anotherTypeEq(self):
|
||||||
|
"""
|
||||||
|
The object does not compare equal to an object of an unrelated type
|
||||||
|
(which does not implement the comparison) using the C{==} operator.
|
||||||
|
"""
|
||||||
|
a = self.anInstance()
|
||||||
|
b = object()
|
||||||
|
self.assertFalse(a == b)
|
||||||
|
|
||||||
|
|
||||||
|
def test_anotherTypeNe(self):
|
||||||
|
"""
|
||||||
|
The object compares not equal to an object of an unrelated type (which
|
||||||
|
does not implement the comparison) using the C{!=} operator.
|
||||||
|
"""
|
||||||
|
a = self.anInstance()
|
||||||
|
b = object()
|
||||||
|
self.assertTrue(a != b)
|
||||||
|
|
||||||
|
|
||||||
|
def test_delegatedEq(self):
|
||||||
|
"""
|
||||||
|
The result of comparison using C{==} is delegated to the right-hand
|
||||||
|
operand if it is of an unrelated type.
|
||||||
|
"""
|
||||||
|
class Delegate(object):
|
||||||
|
def __eq__(self, other):
|
||||||
|
# Do something crazy and obvious.
|
||||||
|
return [self]
|
||||||
|
|
||||||
|
a = self.anInstance()
|
||||||
|
b = Delegate()
|
||||||
|
self.assertEqual(a == b, [b])
|
||||||
|
|
||||||
|
|
||||||
|
def test_delegateNe(self):
|
||||||
|
"""
|
||||||
|
The result of comparison using C{!=} is delegated to the right-hand
|
||||||
|
operand if it is of an unrelated type.
|
||||||
|
"""
|
||||||
|
class Delegate(object):
|
||||||
|
def __ne__(self, other):
|
||||||
|
# Do something crazy and obvious.
|
||||||
|
return [self]
|
||||||
|
|
||||||
|
a = self.anInstance()
|
||||||
|
b = Delegate()
|
||||||
|
self.assertEqual(a != b, [b])
|
||||||
|
|
||||||
|
|
||||||
|
# The type name expected in warnings about using the wrong string type.
|
||||||
|
if PY3:
|
||||||
|
WARNING_TYPE_EXPECTED = "str"
|
||||||
|
else:
|
||||||
|
WARNING_TYPE_EXPECTED = "unicode"
|
||||||
|
|
|
@ -8,7 +8,7 @@ del threading
|
||||||
|
|
||||||
class Connection:
|
class Connection:
|
||||||
def __init__(self, *args):
|
def __init__(self, *args):
|
||||||
self._ssl_conn = apply(_ssl.Connection, args)
|
self._ssl_conn = _ssl.Connection(*args)
|
||||||
self._lock = _RLock()
|
self._lock = _RLock()
|
||||||
|
|
||||||
for f in ('get_context', 'pending', 'send', 'write', 'recv', 'read',
|
for f in ('get_context', 'pending', 'send', 'write', 'recv', 'read',
|
||||||
|
|
|
@ -6,4 +6,4 @@
|
||||||
pyOpenSSL - A simple wrapper around the OpenSSL library
|
pyOpenSSL - A simple wrapper around the OpenSSL library
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__version__ = '0.14'
|
__version__ = '0.15.1'
|
||||||
|
|
|
@ -1,361 +1,361 @@
|
||||||
../sqlalchemy/interfaces.py
|
|
||||||
../sqlalchemy/events.py
|
|
||||||
../sqlalchemy/types.py
|
|
||||||
../sqlalchemy/exc.py
|
|
||||||
../sqlalchemy/schema.py
|
|
||||||
../sqlalchemy/inspection.py
|
|
||||||
../sqlalchemy/__init__.py
|
../sqlalchemy/__init__.py
|
||||||
|
../sqlalchemy/events.py
|
||||||
|
../sqlalchemy/exc.py
|
||||||
|
../sqlalchemy/inspection.py
|
||||||
|
../sqlalchemy/interfaces.py
|
||||||
|
../sqlalchemy/log.py
|
||||||
../sqlalchemy/pool.py
|
../sqlalchemy/pool.py
|
||||||
../sqlalchemy/processors.py
|
../sqlalchemy/processors.py
|
||||||
../sqlalchemy/log.py
|
../sqlalchemy/schema.py
|
||||||
|
../sqlalchemy/types.py
|
||||||
|
../sqlalchemy/connectors/__init__.py
|
||||||
|
../sqlalchemy/connectors/mxodbc.py
|
||||||
|
../sqlalchemy/connectors/mysqldb.py
|
||||||
|
../sqlalchemy/connectors/pyodbc.py
|
||||||
|
../sqlalchemy/connectors/zxJDBC.py
|
||||||
../sqlalchemy/databases/__init__.py
|
../sqlalchemy/databases/__init__.py
|
||||||
../sqlalchemy/testing/engines.py
|
../sqlalchemy/dialects/__init__.py
|
||||||
../sqlalchemy/testing/schema.py
|
../sqlalchemy/dialects/postgres.py
|
||||||
../sqlalchemy/testing/pickleable.py
|
../sqlalchemy/dialects/drizzle/__init__.py
|
||||||
../sqlalchemy/testing/fixtures.py
|
../sqlalchemy/dialects/drizzle/base.py
|
||||||
|
../sqlalchemy/dialects/drizzle/mysqldb.py
|
||||||
|
../sqlalchemy/dialects/firebird/__init__.py
|
||||||
|
../sqlalchemy/dialects/firebird/base.py
|
||||||
|
../sqlalchemy/dialects/firebird/fdb.py
|
||||||
|
../sqlalchemy/dialects/firebird/kinterbasdb.py
|
||||||
|
../sqlalchemy/dialects/mssql/__init__.py
|
||||||
|
../sqlalchemy/dialects/mssql/adodbapi.py
|
||||||
|
../sqlalchemy/dialects/mssql/base.py
|
||||||
|
../sqlalchemy/dialects/mssql/information_schema.py
|
||||||
|
../sqlalchemy/dialects/mssql/mxodbc.py
|
||||||
|
../sqlalchemy/dialects/mssql/pymssql.py
|
||||||
|
../sqlalchemy/dialects/mssql/pyodbc.py
|
||||||
|
../sqlalchemy/dialects/mssql/zxjdbc.py
|
||||||
|
../sqlalchemy/dialects/mysql/__init__.py
|
||||||
|
../sqlalchemy/dialects/mysql/base.py
|
||||||
|
../sqlalchemy/dialects/mysql/cymysql.py
|
||||||
|
../sqlalchemy/dialects/mysql/gaerdbms.py
|
||||||
|
../sqlalchemy/dialects/mysql/mysqlconnector.py
|
||||||
|
../sqlalchemy/dialects/mysql/mysqldb.py
|
||||||
|
../sqlalchemy/dialects/mysql/oursql.py
|
||||||
|
../sqlalchemy/dialects/mysql/pymysql.py
|
||||||
|
../sqlalchemy/dialects/mysql/pyodbc.py
|
||||||
|
../sqlalchemy/dialects/mysql/zxjdbc.py
|
||||||
|
../sqlalchemy/dialects/oracle/__init__.py
|
||||||
|
../sqlalchemy/dialects/oracle/base.py
|
||||||
|
../sqlalchemy/dialects/oracle/cx_oracle.py
|
||||||
|
../sqlalchemy/dialects/oracle/zxjdbc.py
|
||||||
|
../sqlalchemy/dialects/postgresql/__init__.py
|
||||||
|
../sqlalchemy/dialects/postgresql/base.py
|
||||||
|
../sqlalchemy/dialects/postgresql/constraints.py
|
||||||
|
../sqlalchemy/dialects/postgresql/hstore.py
|
||||||
|
../sqlalchemy/dialects/postgresql/json.py
|
||||||
|
../sqlalchemy/dialects/postgresql/pg8000.py
|
||||||
|
../sqlalchemy/dialects/postgresql/psycopg2.py
|
||||||
|
../sqlalchemy/dialects/postgresql/pypostgresql.py
|
||||||
|
../sqlalchemy/dialects/postgresql/ranges.py
|
||||||
|
../sqlalchemy/dialects/postgresql/zxjdbc.py
|
||||||
|
../sqlalchemy/dialects/sqlite/__init__.py
|
||||||
|
../sqlalchemy/dialects/sqlite/base.py
|
||||||
|
../sqlalchemy/dialects/sqlite/pysqlite.py
|
||||||
|
../sqlalchemy/dialects/sybase/__init__.py
|
||||||
|
../sqlalchemy/dialects/sybase/base.py
|
||||||
|
../sqlalchemy/dialects/sybase/mxodbc.py
|
||||||
|
../sqlalchemy/dialects/sybase/pyodbc.py
|
||||||
|
../sqlalchemy/dialects/sybase/pysybase.py
|
||||||
|
../sqlalchemy/engine/__init__.py
|
||||||
|
../sqlalchemy/engine/base.py
|
||||||
|
../sqlalchemy/engine/default.py
|
||||||
|
../sqlalchemy/engine/interfaces.py
|
||||||
|
../sqlalchemy/engine/reflection.py
|
||||||
|
../sqlalchemy/engine/result.py
|
||||||
|
../sqlalchemy/engine/strategies.py
|
||||||
|
../sqlalchemy/engine/threadlocal.py
|
||||||
|
../sqlalchemy/engine/url.py
|
||||||
|
../sqlalchemy/engine/util.py
|
||||||
|
../sqlalchemy/event/__init__.py
|
||||||
|
../sqlalchemy/event/api.py
|
||||||
|
../sqlalchemy/event/attr.py
|
||||||
|
../sqlalchemy/event/base.py
|
||||||
|
../sqlalchemy/event/legacy.py
|
||||||
|
../sqlalchemy/event/registry.py
|
||||||
|
../sqlalchemy/ext/__init__.py
|
||||||
|
../sqlalchemy/ext/associationproxy.py
|
||||||
|
../sqlalchemy/ext/automap.py
|
||||||
|
../sqlalchemy/ext/compiler.py
|
||||||
|
../sqlalchemy/ext/horizontal_shard.py
|
||||||
|
../sqlalchemy/ext/hybrid.py
|
||||||
|
../sqlalchemy/ext/instrumentation.py
|
||||||
|
../sqlalchemy/ext/mutable.py
|
||||||
|
../sqlalchemy/ext/orderinglist.py
|
||||||
|
../sqlalchemy/ext/serializer.py
|
||||||
|
../sqlalchemy/ext/declarative/__init__.py
|
||||||
|
../sqlalchemy/ext/declarative/api.py
|
||||||
|
../sqlalchemy/ext/declarative/base.py
|
||||||
|
../sqlalchemy/ext/declarative/clsregistry.py
|
||||||
|
../sqlalchemy/orm/__init__.py
|
||||||
|
../sqlalchemy/orm/attributes.py
|
||||||
|
../sqlalchemy/orm/base.py
|
||||||
|
../sqlalchemy/orm/collections.py
|
||||||
|
../sqlalchemy/orm/dependency.py
|
||||||
|
../sqlalchemy/orm/deprecated_interfaces.py
|
||||||
|
../sqlalchemy/orm/descriptor_props.py
|
||||||
|
../sqlalchemy/orm/dynamic.py
|
||||||
|
../sqlalchemy/orm/evaluator.py
|
||||||
|
../sqlalchemy/orm/events.py
|
||||||
|
../sqlalchemy/orm/exc.py
|
||||||
|
../sqlalchemy/orm/identity.py
|
||||||
|
../sqlalchemy/orm/instrumentation.py
|
||||||
|
../sqlalchemy/orm/interfaces.py
|
||||||
|
../sqlalchemy/orm/loading.py
|
||||||
|
../sqlalchemy/orm/mapper.py
|
||||||
|
../sqlalchemy/orm/path_registry.py
|
||||||
|
../sqlalchemy/orm/persistence.py
|
||||||
|
../sqlalchemy/orm/properties.py
|
||||||
|
../sqlalchemy/orm/query.py
|
||||||
|
../sqlalchemy/orm/relationships.py
|
||||||
|
../sqlalchemy/orm/scoping.py
|
||||||
|
../sqlalchemy/orm/session.py
|
||||||
|
../sqlalchemy/orm/state.py
|
||||||
|
../sqlalchemy/orm/strategies.py
|
||||||
|
../sqlalchemy/orm/strategy_options.py
|
||||||
|
../sqlalchemy/orm/sync.py
|
||||||
|
../sqlalchemy/orm/unitofwork.py
|
||||||
|
../sqlalchemy/orm/util.py
|
||||||
|
../sqlalchemy/sql/__init__.py
|
||||||
|
../sqlalchemy/sql/annotation.py
|
||||||
|
../sqlalchemy/sql/base.py
|
||||||
|
../sqlalchemy/sql/compiler.py
|
||||||
|
../sqlalchemy/sql/ddl.py
|
||||||
|
../sqlalchemy/sql/default_comparator.py
|
||||||
|
../sqlalchemy/sql/dml.py
|
||||||
|
../sqlalchemy/sql/elements.py
|
||||||
|
../sqlalchemy/sql/expression.py
|
||||||
|
../sqlalchemy/sql/functions.py
|
||||||
|
../sqlalchemy/sql/naming.py
|
||||||
|
../sqlalchemy/sql/operators.py
|
||||||
|
../sqlalchemy/sql/schema.py
|
||||||
|
../sqlalchemy/sql/selectable.py
|
||||||
|
../sqlalchemy/sql/sqltypes.py
|
||||||
|
../sqlalchemy/sql/type_api.py
|
||||||
|
../sqlalchemy/sql/util.py
|
||||||
|
../sqlalchemy/sql/visitors.py
|
||||||
../sqlalchemy/testing/__init__.py
|
../sqlalchemy/testing/__init__.py
|
||||||
|
../sqlalchemy/testing/assertions.py
|
||||||
../sqlalchemy/testing/assertsql.py
|
../sqlalchemy/testing/assertsql.py
|
||||||
../sqlalchemy/testing/config.py
|
../sqlalchemy/testing/config.py
|
||||||
../sqlalchemy/testing/warnings.py
|
|
||||||
../sqlalchemy/testing/distutils_run.py
|
../sqlalchemy/testing/distutils_run.py
|
||||||
|
../sqlalchemy/testing/engines.py
|
||||||
|
../sqlalchemy/testing/entities.py
|
||||||
|
../sqlalchemy/testing/exclusions.py
|
||||||
|
../sqlalchemy/testing/fixtures.py
|
||||||
|
../sqlalchemy/testing/mock.py
|
||||||
|
../sqlalchemy/testing/pickleable.py
|
||||||
|
../sqlalchemy/testing/profiling.py
|
||||||
../sqlalchemy/testing/requirements.py
|
../sqlalchemy/testing/requirements.py
|
||||||
../sqlalchemy/testing/runner.py
|
../sqlalchemy/testing/runner.py
|
||||||
../sqlalchemy/testing/assertions.py
|
../sqlalchemy/testing/schema.py
|
||||||
../sqlalchemy/testing/profiling.py
|
|
||||||
../sqlalchemy/testing/mock.py
|
|
||||||
../sqlalchemy/testing/exclusions.py
|
|
||||||
../sqlalchemy/testing/util.py
|
../sqlalchemy/testing/util.py
|
||||||
../sqlalchemy/testing/entities.py
|
../sqlalchemy/testing/warnings.py
|
||||||
../sqlalchemy/testing/plugin/noseplugin.py
|
|
||||||
../sqlalchemy/testing/plugin/__init__.py
|
../sqlalchemy/testing/plugin/__init__.py
|
||||||
../sqlalchemy/testing/plugin/pytestplugin.py
|
../sqlalchemy/testing/plugin/noseplugin.py
|
||||||
../sqlalchemy/testing/plugin/plugin_base.py
|
../sqlalchemy/testing/plugin/plugin_base.py
|
||||||
../sqlalchemy/testing/suite/test_insert.py
|
../sqlalchemy/testing/plugin/pytestplugin.py
|
||||||
../sqlalchemy/testing/suite/test_results.py
|
|
||||||
../sqlalchemy/testing/suite/__init__.py
|
../sqlalchemy/testing/suite/__init__.py
|
||||||
|
../sqlalchemy/testing/suite/test_ddl.py
|
||||||
|
../sqlalchemy/testing/suite/test_insert.py
|
||||||
|
../sqlalchemy/testing/suite/test_reflection.py
|
||||||
|
../sqlalchemy/testing/suite/test_results.py
|
||||||
../sqlalchemy/testing/suite/test_select.py
|
../sqlalchemy/testing/suite/test_select.py
|
||||||
../sqlalchemy/testing/suite/test_sequence.py
|
../sqlalchemy/testing/suite/test_sequence.py
|
||||||
../sqlalchemy/testing/suite/test_types.py
|
../sqlalchemy/testing/suite/test_types.py
|
||||||
../sqlalchemy/testing/suite/test_update_delete.py
|
../sqlalchemy/testing/suite/test_update_delete.py
|
||||||
../sqlalchemy/testing/suite/test_reflection.py
|
../sqlalchemy/util/__init__.py
|
||||||
../sqlalchemy/testing/suite/test_ddl.py
|
../sqlalchemy/util/_collections.py
|
||||||
../sqlalchemy/orm/persistence.py
|
../sqlalchemy/util/compat.py
|
||||||
../sqlalchemy/orm/interfaces.py
|
../sqlalchemy/util/deprecations.py
|
||||||
../sqlalchemy/orm/events.py
|
|
||||||
../sqlalchemy/orm/path_registry.py
|
|
||||||
../sqlalchemy/orm/descriptor_props.py
|
|
||||||
../sqlalchemy/orm/identity.py
|
|
||||||
../sqlalchemy/orm/evaluator.py
|
|
||||||
../sqlalchemy/orm/exc.py
|
|
||||||
../sqlalchemy/orm/base.py
|
|
||||||
../sqlalchemy/orm/__init__.py
|
|
||||||
../sqlalchemy/orm/properties.py
|
|
||||||
../sqlalchemy/orm/relationships.py
|
|
||||||
../sqlalchemy/orm/collections.py
|
|
||||||
../sqlalchemy/orm/strategy_options.py
|
|
||||||
../sqlalchemy/orm/dynamic.py
|
|
||||||
../sqlalchemy/orm/attributes.py
|
|
||||||
../sqlalchemy/orm/mapper.py
|
|
||||||
../sqlalchemy/orm/state.py
|
|
||||||
../sqlalchemy/orm/sync.py
|
|
||||||
../sqlalchemy/orm/loading.py
|
|
||||||
../sqlalchemy/orm/strategies.py
|
|
||||||
../sqlalchemy/orm/unitofwork.py
|
|
||||||
../sqlalchemy/orm/query.py
|
|
||||||
../sqlalchemy/orm/instrumentation.py
|
|
||||||
../sqlalchemy/orm/session.py
|
|
||||||
../sqlalchemy/orm/deprecated_interfaces.py
|
|
||||||
../sqlalchemy/orm/scoping.py
|
|
||||||
../sqlalchemy/orm/dependency.py
|
|
||||||
../sqlalchemy/orm/util.py
|
|
||||||
../sqlalchemy/sql/default_comparator.py
|
|
||||||
../sqlalchemy/sql/sqltypes.py
|
|
||||||
../sqlalchemy/sql/functions.py
|
|
||||||
../sqlalchemy/sql/base.py
|
|
||||||
../sqlalchemy/sql/schema.py
|
|
||||||
../sqlalchemy/sql/__init__.py
|
|
||||||
../sqlalchemy/sql/ddl.py
|
|
||||||
../sqlalchemy/sql/elements.py
|
|
||||||
../sqlalchemy/sql/compiler.py
|
|
||||||
../sqlalchemy/sql/annotation.py
|
|
||||||
../sqlalchemy/sql/dml.py
|
|
||||||
../sqlalchemy/sql/expression.py
|
|
||||||
../sqlalchemy/sql/operators.py
|
|
||||||
../sqlalchemy/sql/selectable.py
|
|
||||||
../sqlalchemy/sql/visitors.py
|
|
||||||
../sqlalchemy/sql/type_api.py
|
|
||||||
../sqlalchemy/sql/naming.py
|
|
||||||
../sqlalchemy/sql/util.py
|
|
||||||
../sqlalchemy/ext/serializer.py
|
|
||||||
../sqlalchemy/ext/associationproxy.py
|
|
||||||
../sqlalchemy/ext/automap.py
|
|
||||||
../sqlalchemy/ext/__init__.py
|
|
||||||
../sqlalchemy/ext/hybrid.py
|
|
||||||
../sqlalchemy/ext/compiler.py
|
|
||||||
../sqlalchemy/ext/horizontal_shard.py
|
|
||||||
../sqlalchemy/ext/orderinglist.py
|
|
||||||
../sqlalchemy/ext/instrumentation.py
|
|
||||||
../sqlalchemy/ext/mutable.py
|
|
||||||
../sqlalchemy/ext/declarative/base.py
|
|
||||||
../sqlalchemy/ext/declarative/__init__.py
|
|
||||||
../sqlalchemy/ext/declarative/clsregistry.py
|
|
||||||
../sqlalchemy/ext/declarative/api.py
|
|
||||||
../sqlalchemy/util/langhelpers.py
|
../sqlalchemy/util/langhelpers.py
|
||||||
../sqlalchemy/util/queue.py
|
../sqlalchemy/util/queue.py
|
||||||
../sqlalchemy/util/compat.py
|
|
||||||
../sqlalchemy/util/__init__.py
|
|
||||||
../sqlalchemy/util/deprecations.py
|
|
||||||
../sqlalchemy/util/_collections.py
|
|
||||||
../sqlalchemy/util/topological.py
|
../sqlalchemy/util/topological.py
|
||||||
../sqlalchemy/connectors/mxodbc.py
|
|
||||||
../sqlalchemy/connectors/__init__.py
|
|
||||||
../sqlalchemy/connectors/pyodbc.py
|
|
||||||
../sqlalchemy/connectors/mysqldb.py
|
|
||||||
../sqlalchemy/connectors/zxJDBC.py
|
|
||||||
../sqlalchemy/dialects/postgres.py
|
|
||||||
../sqlalchemy/dialects/__init__.py
|
|
||||||
../sqlalchemy/dialects/mssql/adodbapi.py
|
|
||||||
../sqlalchemy/dialects/mssql/mxodbc.py
|
|
||||||
../sqlalchemy/dialects/mssql/base.py
|
|
||||||
../sqlalchemy/dialects/mssql/information_schema.py
|
|
||||||
../sqlalchemy/dialects/mssql/__init__.py
|
|
||||||
../sqlalchemy/dialects/mssql/pyodbc.py
|
|
||||||
../sqlalchemy/dialects/mssql/zxjdbc.py
|
|
||||||
../sqlalchemy/dialects/mssql/pymssql.py
|
|
||||||
../sqlalchemy/dialects/postgresql/pg8000.py
|
|
||||||
../sqlalchemy/dialects/postgresql/ranges.py
|
|
||||||
../sqlalchemy/dialects/postgresql/base.py
|
|
||||||
../sqlalchemy/dialects/postgresql/__init__.py
|
|
||||||
../sqlalchemy/dialects/postgresql/zxjdbc.py
|
|
||||||
../sqlalchemy/dialects/postgresql/json.py
|
|
||||||
../sqlalchemy/dialects/postgresql/pypostgresql.py
|
|
||||||
../sqlalchemy/dialects/postgresql/constraints.py
|
|
||||||
../sqlalchemy/dialects/postgresql/hstore.py
|
|
||||||
../sqlalchemy/dialects/postgresql/psycopg2.py
|
|
||||||
../sqlalchemy/dialects/sybase/mxodbc.py
|
|
||||||
../sqlalchemy/dialects/sybase/base.py
|
|
||||||
../sqlalchemy/dialects/sybase/__init__.py
|
|
||||||
../sqlalchemy/dialects/sybase/pyodbc.py
|
|
||||||
../sqlalchemy/dialects/sybase/pysybase.py
|
|
||||||
../sqlalchemy/dialects/drizzle/base.py
|
|
||||||
../sqlalchemy/dialects/drizzle/__init__.py
|
|
||||||
../sqlalchemy/dialects/drizzle/mysqldb.py
|
|
||||||
../sqlalchemy/dialects/mysql/mysqlconnector.py
|
|
||||||
../sqlalchemy/dialects/mysql/base.py
|
|
||||||
../sqlalchemy/dialects/mysql/__init__.py
|
|
||||||
../sqlalchemy/dialects/mysql/pyodbc.py
|
|
||||||
../sqlalchemy/dialects/mysql/zxjdbc.py
|
|
||||||
../sqlalchemy/dialects/mysql/oursql.py
|
|
||||||
../sqlalchemy/dialects/mysql/pymysql.py
|
|
||||||
../sqlalchemy/dialects/mysql/cymysql.py
|
|
||||||
../sqlalchemy/dialects/mysql/gaerdbms.py
|
|
||||||
../sqlalchemy/dialects/mysql/mysqldb.py
|
|
||||||
../sqlalchemy/dialects/sqlite/base.py
|
|
||||||
../sqlalchemy/dialects/sqlite/__init__.py
|
|
||||||
../sqlalchemy/dialects/sqlite/pysqlite.py
|
|
||||||
../sqlalchemy/dialects/firebird/base.py
|
|
||||||
../sqlalchemy/dialects/firebird/__init__.py
|
|
||||||
../sqlalchemy/dialects/firebird/fdb.py
|
|
||||||
../sqlalchemy/dialects/firebird/kinterbasdb.py
|
|
||||||
../sqlalchemy/dialects/oracle/base.py
|
|
||||||
../sqlalchemy/dialects/oracle/__init__.py
|
|
||||||
../sqlalchemy/dialects/oracle/zxjdbc.py
|
|
||||||
../sqlalchemy/dialects/oracle/cx_oracle.py
|
|
||||||
../sqlalchemy/engine/interfaces.py
|
|
||||||
../sqlalchemy/engine/result.py
|
|
||||||
../sqlalchemy/engine/base.py
|
|
||||||
../sqlalchemy/engine/url.py
|
|
||||||
../sqlalchemy/engine/threadlocal.py
|
|
||||||
../sqlalchemy/engine/__init__.py
|
|
||||||
../sqlalchemy/engine/default.py
|
|
||||||
../sqlalchemy/engine/strategies.py
|
|
||||||
../sqlalchemy/engine/reflection.py
|
|
||||||
../sqlalchemy/engine/util.py
|
|
||||||
../sqlalchemy/event/base.py
|
|
||||||
../sqlalchemy/event/__init__.py
|
|
||||||
../sqlalchemy/event/attr.py
|
|
||||||
../sqlalchemy/event/registry.py
|
|
||||||
../sqlalchemy/event/legacy.py
|
|
||||||
../sqlalchemy/event/api.py
|
|
||||||
../sqlalchemy/__pycache__/interfaces.cpython-34.pyc
|
|
||||||
../sqlalchemy/__pycache__/events.cpython-34.pyc
|
|
||||||
../sqlalchemy/__pycache__/types.cpython-34.pyc
|
|
||||||
../sqlalchemy/__pycache__/exc.cpython-34.pyc
|
|
||||||
../sqlalchemy/__pycache__/schema.cpython-34.pyc
|
|
||||||
../sqlalchemy/__pycache__/inspection.cpython-34.pyc
|
|
||||||
../sqlalchemy/__pycache__/__init__.cpython-34.pyc
|
../sqlalchemy/__pycache__/__init__.cpython-34.pyc
|
||||||
|
../sqlalchemy/__pycache__/events.cpython-34.pyc
|
||||||
|
../sqlalchemy/__pycache__/exc.cpython-34.pyc
|
||||||
|
../sqlalchemy/__pycache__/inspection.cpython-34.pyc
|
||||||
|
../sqlalchemy/__pycache__/interfaces.cpython-34.pyc
|
||||||
|
../sqlalchemy/__pycache__/log.cpython-34.pyc
|
||||||
../sqlalchemy/__pycache__/pool.cpython-34.pyc
|
../sqlalchemy/__pycache__/pool.cpython-34.pyc
|
||||||
../sqlalchemy/__pycache__/processors.cpython-34.pyc
|
../sqlalchemy/__pycache__/processors.cpython-34.pyc
|
||||||
../sqlalchemy/__pycache__/log.cpython-34.pyc
|
../sqlalchemy/__pycache__/schema.cpython-34.pyc
|
||||||
|
../sqlalchemy/__pycache__/types.cpython-34.pyc
|
||||||
|
../sqlalchemy/connectors/__pycache__/__init__.cpython-34.pyc
|
||||||
|
../sqlalchemy/connectors/__pycache__/mxodbc.cpython-34.pyc
|
||||||
|
../sqlalchemy/connectors/__pycache__/mysqldb.cpython-34.pyc
|
||||||
|
../sqlalchemy/connectors/__pycache__/pyodbc.cpython-34.pyc
|
||||||
|
../sqlalchemy/connectors/__pycache__/zxJDBC.cpython-34.pyc
|
||||||
../sqlalchemy/databases/__pycache__/__init__.cpython-34.pyc
|
../sqlalchemy/databases/__pycache__/__init__.cpython-34.pyc
|
||||||
../sqlalchemy/testing/__pycache__/engines.cpython-34.pyc
|
../sqlalchemy/dialects/__pycache__/__init__.cpython-34.pyc
|
||||||
../sqlalchemy/testing/__pycache__/schema.cpython-34.pyc
|
../sqlalchemy/dialects/__pycache__/postgres.cpython-34.pyc
|
||||||
../sqlalchemy/testing/__pycache__/pickleable.cpython-34.pyc
|
../sqlalchemy/dialects/drizzle/__pycache__/__init__.cpython-34.pyc
|
||||||
../sqlalchemy/testing/__pycache__/fixtures.cpython-34.pyc
|
../sqlalchemy/dialects/drizzle/__pycache__/base.cpython-34.pyc
|
||||||
|
../sqlalchemy/dialects/drizzle/__pycache__/mysqldb.cpython-34.pyc
|
||||||
|
../sqlalchemy/dialects/firebird/__pycache__/__init__.cpython-34.pyc
|
||||||
|
../sqlalchemy/dialects/firebird/__pycache__/base.cpython-34.pyc
|
||||||
|
../sqlalchemy/dialects/firebird/__pycache__/fdb.cpython-34.pyc
|
||||||
|
../sqlalchemy/dialects/firebird/__pycache__/kinterbasdb.cpython-34.pyc
|
||||||
|
../sqlalchemy/dialects/mssql/__pycache__/__init__.cpython-34.pyc
|
||||||
|
../sqlalchemy/dialects/mssql/__pycache__/adodbapi.cpython-34.pyc
|
||||||
|
../sqlalchemy/dialects/mssql/__pycache__/base.cpython-34.pyc
|
||||||
|
../sqlalchemy/dialects/mssql/__pycache__/information_schema.cpython-34.pyc
|
||||||
|
../sqlalchemy/dialects/mssql/__pycache__/mxodbc.cpython-34.pyc
|
||||||
|
../sqlalchemy/dialects/mssql/__pycache__/pymssql.cpython-34.pyc
|
||||||
|
../sqlalchemy/dialects/mssql/__pycache__/pyodbc.cpython-34.pyc
|
||||||
|
../sqlalchemy/dialects/mssql/__pycache__/zxjdbc.cpython-34.pyc
|
||||||
|
../sqlalchemy/dialects/mysql/__pycache__/__init__.cpython-34.pyc
|
||||||
|
../sqlalchemy/dialects/mysql/__pycache__/base.cpython-34.pyc
|
||||||
|
../sqlalchemy/dialects/mysql/__pycache__/cymysql.cpython-34.pyc
|
||||||
|
../sqlalchemy/dialects/mysql/__pycache__/gaerdbms.cpython-34.pyc
|
||||||
|
../sqlalchemy/dialects/mysql/__pycache__/mysqlconnector.cpython-34.pyc
|
||||||
|
../sqlalchemy/dialects/mysql/__pycache__/mysqldb.cpython-34.pyc
|
||||||
|
../sqlalchemy/dialects/mysql/__pycache__/oursql.cpython-34.pyc
|
||||||
|
../sqlalchemy/dialects/mysql/__pycache__/pymysql.cpython-34.pyc
|
||||||
|
../sqlalchemy/dialects/mysql/__pycache__/pyodbc.cpython-34.pyc
|
||||||
|
../sqlalchemy/dialects/mysql/__pycache__/zxjdbc.cpython-34.pyc
|
||||||
|
../sqlalchemy/dialects/oracle/__pycache__/__init__.cpython-34.pyc
|
||||||
|
../sqlalchemy/dialects/oracle/__pycache__/base.cpython-34.pyc
|
||||||
|
../sqlalchemy/dialects/oracle/__pycache__/cx_oracle.cpython-34.pyc
|
||||||
|
../sqlalchemy/dialects/oracle/__pycache__/zxjdbc.cpython-34.pyc
|
||||||
|
../sqlalchemy/dialects/postgresql/__pycache__/__init__.cpython-34.pyc
|
||||||
|
../sqlalchemy/dialects/postgresql/__pycache__/base.cpython-34.pyc
|
||||||
|
../sqlalchemy/dialects/postgresql/__pycache__/constraints.cpython-34.pyc
|
||||||
|
../sqlalchemy/dialects/postgresql/__pycache__/hstore.cpython-34.pyc
|
||||||
|
../sqlalchemy/dialects/postgresql/__pycache__/json.cpython-34.pyc
|
||||||
|
../sqlalchemy/dialects/postgresql/__pycache__/pg8000.cpython-34.pyc
|
||||||
|
../sqlalchemy/dialects/postgresql/__pycache__/psycopg2.cpython-34.pyc
|
||||||
|
../sqlalchemy/dialects/postgresql/__pycache__/pypostgresql.cpython-34.pyc
|
||||||
|
../sqlalchemy/dialects/postgresql/__pycache__/ranges.cpython-34.pyc
|
||||||
|
../sqlalchemy/dialects/postgresql/__pycache__/zxjdbc.cpython-34.pyc
|
||||||
|
../sqlalchemy/dialects/sqlite/__pycache__/__init__.cpython-34.pyc
|
||||||
|
../sqlalchemy/dialects/sqlite/__pycache__/base.cpython-34.pyc
|
||||||
|
../sqlalchemy/dialects/sqlite/__pycache__/pysqlite.cpython-34.pyc
|
||||||
|
../sqlalchemy/dialects/sybase/__pycache__/__init__.cpython-34.pyc
|
||||||
|
../sqlalchemy/dialects/sybase/__pycache__/base.cpython-34.pyc
|
||||||
|
../sqlalchemy/dialects/sybase/__pycache__/mxodbc.cpython-34.pyc
|
||||||
|
../sqlalchemy/dialects/sybase/__pycache__/pyodbc.cpython-34.pyc
|
||||||
|
../sqlalchemy/dialects/sybase/__pycache__/pysybase.cpython-34.pyc
|
||||||
|
../sqlalchemy/engine/__pycache__/__init__.cpython-34.pyc
|
||||||
|
../sqlalchemy/engine/__pycache__/base.cpython-34.pyc
|
||||||
|
../sqlalchemy/engine/__pycache__/default.cpython-34.pyc
|
||||||
|
../sqlalchemy/engine/__pycache__/interfaces.cpython-34.pyc
|
||||||
|
../sqlalchemy/engine/__pycache__/reflection.cpython-34.pyc
|
||||||
|
../sqlalchemy/engine/__pycache__/result.cpython-34.pyc
|
||||||
|
../sqlalchemy/engine/__pycache__/strategies.cpython-34.pyc
|
||||||
|
../sqlalchemy/engine/__pycache__/threadlocal.cpython-34.pyc
|
||||||
|
../sqlalchemy/engine/__pycache__/url.cpython-34.pyc
|
||||||
|
../sqlalchemy/engine/__pycache__/util.cpython-34.pyc
|
||||||
|
../sqlalchemy/event/__pycache__/__init__.cpython-34.pyc
|
||||||
|
../sqlalchemy/event/__pycache__/api.cpython-34.pyc
|
||||||
|
../sqlalchemy/event/__pycache__/attr.cpython-34.pyc
|
||||||
|
../sqlalchemy/event/__pycache__/base.cpython-34.pyc
|
||||||
|
../sqlalchemy/event/__pycache__/legacy.cpython-34.pyc
|
||||||
|
../sqlalchemy/event/__pycache__/registry.cpython-34.pyc
|
||||||
|
../sqlalchemy/ext/__pycache__/__init__.cpython-34.pyc
|
||||||
|
../sqlalchemy/ext/__pycache__/associationproxy.cpython-34.pyc
|
||||||
|
../sqlalchemy/ext/__pycache__/automap.cpython-34.pyc
|
||||||
|
../sqlalchemy/ext/__pycache__/compiler.cpython-34.pyc
|
||||||
|
../sqlalchemy/ext/__pycache__/horizontal_shard.cpython-34.pyc
|
||||||
|
../sqlalchemy/ext/__pycache__/hybrid.cpython-34.pyc
|
||||||
|
../sqlalchemy/ext/__pycache__/instrumentation.cpython-34.pyc
|
||||||
|
../sqlalchemy/ext/__pycache__/mutable.cpython-34.pyc
|
||||||
|
../sqlalchemy/ext/__pycache__/orderinglist.cpython-34.pyc
|
||||||
|
../sqlalchemy/ext/__pycache__/serializer.cpython-34.pyc
|
||||||
|
../sqlalchemy/ext/declarative/__pycache__/__init__.cpython-34.pyc
|
||||||
|
../sqlalchemy/ext/declarative/__pycache__/api.cpython-34.pyc
|
||||||
|
../sqlalchemy/ext/declarative/__pycache__/base.cpython-34.pyc
|
||||||
|
../sqlalchemy/ext/declarative/__pycache__/clsregistry.cpython-34.pyc
|
||||||
|
../sqlalchemy/orm/__pycache__/__init__.cpython-34.pyc
|
||||||
|
../sqlalchemy/orm/__pycache__/attributes.cpython-34.pyc
|
||||||
|
../sqlalchemy/orm/__pycache__/base.cpython-34.pyc
|
||||||
|
../sqlalchemy/orm/__pycache__/collections.cpython-34.pyc
|
||||||
|
../sqlalchemy/orm/__pycache__/dependency.cpython-34.pyc
|
||||||
|
../sqlalchemy/orm/__pycache__/deprecated_interfaces.cpython-34.pyc
|
||||||
|
../sqlalchemy/orm/__pycache__/descriptor_props.cpython-34.pyc
|
||||||
|
../sqlalchemy/orm/__pycache__/dynamic.cpython-34.pyc
|
||||||
|
../sqlalchemy/orm/__pycache__/evaluator.cpython-34.pyc
|
||||||
|
../sqlalchemy/orm/__pycache__/events.cpython-34.pyc
|
||||||
|
../sqlalchemy/orm/__pycache__/exc.cpython-34.pyc
|
||||||
|
../sqlalchemy/orm/__pycache__/identity.cpython-34.pyc
|
||||||
|
../sqlalchemy/orm/__pycache__/instrumentation.cpython-34.pyc
|
||||||
|
../sqlalchemy/orm/__pycache__/interfaces.cpython-34.pyc
|
||||||
|
../sqlalchemy/orm/__pycache__/loading.cpython-34.pyc
|
||||||
|
../sqlalchemy/orm/__pycache__/mapper.cpython-34.pyc
|
||||||
|
../sqlalchemy/orm/__pycache__/path_registry.cpython-34.pyc
|
||||||
|
../sqlalchemy/orm/__pycache__/persistence.cpython-34.pyc
|
||||||
|
../sqlalchemy/orm/__pycache__/properties.cpython-34.pyc
|
||||||
|
../sqlalchemy/orm/__pycache__/query.cpython-34.pyc
|
||||||
|
../sqlalchemy/orm/__pycache__/relationships.cpython-34.pyc
|
||||||
|
../sqlalchemy/orm/__pycache__/scoping.cpython-34.pyc
|
||||||
|
../sqlalchemy/orm/__pycache__/session.cpython-34.pyc
|
||||||
|
../sqlalchemy/orm/__pycache__/state.cpython-34.pyc
|
||||||
|
../sqlalchemy/orm/__pycache__/strategies.cpython-34.pyc
|
||||||
|
../sqlalchemy/orm/__pycache__/strategy_options.cpython-34.pyc
|
||||||
|
../sqlalchemy/orm/__pycache__/sync.cpython-34.pyc
|
||||||
|
../sqlalchemy/orm/__pycache__/unitofwork.cpython-34.pyc
|
||||||
|
../sqlalchemy/orm/__pycache__/util.cpython-34.pyc
|
||||||
|
../sqlalchemy/sql/__pycache__/__init__.cpython-34.pyc
|
||||||
|
../sqlalchemy/sql/__pycache__/annotation.cpython-34.pyc
|
||||||
|
../sqlalchemy/sql/__pycache__/base.cpython-34.pyc
|
||||||
|
../sqlalchemy/sql/__pycache__/compiler.cpython-34.pyc
|
||||||
|
../sqlalchemy/sql/__pycache__/ddl.cpython-34.pyc
|
||||||
|
../sqlalchemy/sql/__pycache__/default_comparator.cpython-34.pyc
|
||||||
|
../sqlalchemy/sql/__pycache__/dml.cpython-34.pyc
|
||||||
|
../sqlalchemy/sql/__pycache__/elements.cpython-34.pyc
|
||||||
|
../sqlalchemy/sql/__pycache__/expression.cpython-34.pyc
|
||||||
|
../sqlalchemy/sql/__pycache__/functions.cpython-34.pyc
|
||||||
|
../sqlalchemy/sql/__pycache__/naming.cpython-34.pyc
|
||||||
|
../sqlalchemy/sql/__pycache__/operators.cpython-34.pyc
|
||||||
|
../sqlalchemy/sql/__pycache__/schema.cpython-34.pyc
|
||||||
|
../sqlalchemy/sql/__pycache__/selectable.cpython-34.pyc
|
||||||
|
../sqlalchemy/sql/__pycache__/sqltypes.cpython-34.pyc
|
||||||
|
../sqlalchemy/sql/__pycache__/type_api.cpython-34.pyc
|
||||||
|
../sqlalchemy/sql/__pycache__/util.cpython-34.pyc
|
||||||
|
../sqlalchemy/sql/__pycache__/visitors.cpython-34.pyc
|
||||||
../sqlalchemy/testing/__pycache__/__init__.cpython-34.pyc
|
../sqlalchemy/testing/__pycache__/__init__.cpython-34.pyc
|
||||||
|
../sqlalchemy/testing/__pycache__/assertions.cpython-34.pyc
|
||||||
../sqlalchemy/testing/__pycache__/assertsql.cpython-34.pyc
|
../sqlalchemy/testing/__pycache__/assertsql.cpython-34.pyc
|
||||||
../sqlalchemy/testing/__pycache__/config.cpython-34.pyc
|
../sqlalchemy/testing/__pycache__/config.cpython-34.pyc
|
||||||
../sqlalchemy/testing/__pycache__/warnings.cpython-34.pyc
|
|
||||||
../sqlalchemy/testing/__pycache__/distutils_run.cpython-34.pyc
|
../sqlalchemy/testing/__pycache__/distutils_run.cpython-34.pyc
|
||||||
|
../sqlalchemy/testing/__pycache__/engines.cpython-34.pyc
|
||||||
|
../sqlalchemy/testing/__pycache__/entities.cpython-34.pyc
|
||||||
|
../sqlalchemy/testing/__pycache__/exclusions.cpython-34.pyc
|
||||||
|
../sqlalchemy/testing/__pycache__/fixtures.cpython-34.pyc
|
||||||
|
../sqlalchemy/testing/__pycache__/mock.cpython-34.pyc
|
||||||
|
../sqlalchemy/testing/__pycache__/pickleable.cpython-34.pyc
|
||||||
|
../sqlalchemy/testing/__pycache__/profiling.cpython-34.pyc
|
||||||
../sqlalchemy/testing/__pycache__/requirements.cpython-34.pyc
|
../sqlalchemy/testing/__pycache__/requirements.cpython-34.pyc
|
||||||
../sqlalchemy/testing/__pycache__/runner.cpython-34.pyc
|
../sqlalchemy/testing/__pycache__/runner.cpython-34.pyc
|
||||||
../sqlalchemy/testing/__pycache__/assertions.cpython-34.pyc
|
../sqlalchemy/testing/__pycache__/schema.cpython-34.pyc
|
||||||
../sqlalchemy/testing/__pycache__/profiling.cpython-34.pyc
|
|
||||||
../sqlalchemy/testing/__pycache__/mock.cpython-34.pyc
|
|
||||||
../sqlalchemy/testing/__pycache__/exclusions.cpython-34.pyc
|
|
||||||
../sqlalchemy/testing/__pycache__/util.cpython-34.pyc
|
../sqlalchemy/testing/__pycache__/util.cpython-34.pyc
|
||||||
../sqlalchemy/testing/__pycache__/entities.cpython-34.pyc
|
../sqlalchemy/testing/__pycache__/warnings.cpython-34.pyc
|
||||||
../sqlalchemy/testing/plugin/__pycache__/noseplugin.cpython-34.pyc
|
|
||||||
../sqlalchemy/testing/plugin/__pycache__/__init__.cpython-34.pyc
|
../sqlalchemy/testing/plugin/__pycache__/__init__.cpython-34.pyc
|
||||||
../sqlalchemy/testing/plugin/__pycache__/pytestplugin.cpython-34.pyc
|
../sqlalchemy/testing/plugin/__pycache__/noseplugin.cpython-34.pyc
|
||||||
../sqlalchemy/testing/plugin/__pycache__/plugin_base.cpython-34.pyc
|
../sqlalchemy/testing/plugin/__pycache__/plugin_base.cpython-34.pyc
|
||||||
../sqlalchemy/testing/suite/__pycache__/test_insert.cpython-34.pyc
|
../sqlalchemy/testing/plugin/__pycache__/pytestplugin.cpython-34.pyc
|
||||||
../sqlalchemy/testing/suite/__pycache__/test_results.cpython-34.pyc
|
|
||||||
../sqlalchemy/testing/suite/__pycache__/__init__.cpython-34.pyc
|
../sqlalchemy/testing/suite/__pycache__/__init__.cpython-34.pyc
|
||||||
|
../sqlalchemy/testing/suite/__pycache__/test_ddl.cpython-34.pyc
|
||||||
|
../sqlalchemy/testing/suite/__pycache__/test_insert.cpython-34.pyc
|
||||||
|
../sqlalchemy/testing/suite/__pycache__/test_reflection.cpython-34.pyc
|
||||||
|
../sqlalchemy/testing/suite/__pycache__/test_results.cpython-34.pyc
|
||||||
../sqlalchemy/testing/suite/__pycache__/test_select.cpython-34.pyc
|
../sqlalchemy/testing/suite/__pycache__/test_select.cpython-34.pyc
|
||||||
../sqlalchemy/testing/suite/__pycache__/test_sequence.cpython-34.pyc
|
../sqlalchemy/testing/suite/__pycache__/test_sequence.cpython-34.pyc
|
||||||
../sqlalchemy/testing/suite/__pycache__/test_types.cpython-34.pyc
|
../sqlalchemy/testing/suite/__pycache__/test_types.cpython-34.pyc
|
||||||
../sqlalchemy/testing/suite/__pycache__/test_update_delete.cpython-34.pyc
|
../sqlalchemy/testing/suite/__pycache__/test_update_delete.cpython-34.pyc
|
||||||
../sqlalchemy/testing/suite/__pycache__/test_reflection.cpython-34.pyc
|
../sqlalchemy/util/__pycache__/__init__.cpython-34.pyc
|
||||||
../sqlalchemy/testing/suite/__pycache__/test_ddl.cpython-34.pyc
|
../sqlalchemy/util/__pycache__/_collections.cpython-34.pyc
|
||||||
../sqlalchemy/orm/__pycache__/persistence.cpython-34.pyc
|
../sqlalchemy/util/__pycache__/compat.cpython-34.pyc
|
||||||
../sqlalchemy/orm/__pycache__/interfaces.cpython-34.pyc
|
../sqlalchemy/util/__pycache__/deprecations.cpython-34.pyc
|
||||||
../sqlalchemy/orm/__pycache__/events.cpython-34.pyc
|
|
||||||
../sqlalchemy/orm/__pycache__/path_registry.cpython-34.pyc
|
|
||||||
../sqlalchemy/orm/__pycache__/descriptor_props.cpython-34.pyc
|
|
||||||
../sqlalchemy/orm/__pycache__/identity.cpython-34.pyc
|
|
||||||
../sqlalchemy/orm/__pycache__/evaluator.cpython-34.pyc
|
|
||||||
../sqlalchemy/orm/__pycache__/exc.cpython-34.pyc
|
|
||||||
../sqlalchemy/orm/__pycache__/base.cpython-34.pyc
|
|
||||||
../sqlalchemy/orm/__pycache__/__init__.cpython-34.pyc
|
|
||||||
../sqlalchemy/orm/__pycache__/properties.cpython-34.pyc
|
|
||||||
../sqlalchemy/orm/__pycache__/relationships.cpython-34.pyc
|
|
||||||
../sqlalchemy/orm/__pycache__/collections.cpython-34.pyc
|
|
||||||
../sqlalchemy/orm/__pycache__/strategy_options.cpython-34.pyc
|
|
||||||
../sqlalchemy/orm/__pycache__/dynamic.cpython-34.pyc
|
|
||||||
../sqlalchemy/orm/__pycache__/attributes.cpython-34.pyc
|
|
||||||
../sqlalchemy/orm/__pycache__/mapper.cpython-34.pyc
|
|
||||||
../sqlalchemy/orm/__pycache__/state.cpython-34.pyc
|
|
||||||
../sqlalchemy/orm/__pycache__/sync.cpython-34.pyc
|
|
||||||
../sqlalchemy/orm/__pycache__/loading.cpython-34.pyc
|
|
||||||
../sqlalchemy/orm/__pycache__/strategies.cpython-34.pyc
|
|
||||||
../sqlalchemy/orm/__pycache__/unitofwork.cpython-34.pyc
|
|
||||||
../sqlalchemy/orm/__pycache__/query.cpython-34.pyc
|
|
||||||
../sqlalchemy/orm/__pycache__/instrumentation.cpython-34.pyc
|
|
||||||
../sqlalchemy/orm/__pycache__/session.cpython-34.pyc
|
|
||||||
../sqlalchemy/orm/__pycache__/deprecated_interfaces.cpython-34.pyc
|
|
||||||
../sqlalchemy/orm/__pycache__/scoping.cpython-34.pyc
|
|
||||||
../sqlalchemy/orm/__pycache__/dependency.cpython-34.pyc
|
|
||||||
../sqlalchemy/orm/__pycache__/util.cpython-34.pyc
|
|
||||||
../sqlalchemy/sql/__pycache__/default_comparator.cpython-34.pyc
|
|
||||||
../sqlalchemy/sql/__pycache__/sqltypes.cpython-34.pyc
|
|
||||||
../sqlalchemy/sql/__pycache__/functions.cpython-34.pyc
|
|
||||||
../sqlalchemy/sql/__pycache__/base.cpython-34.pyc
|
|
||||||
../sqlalchemy/sql/__pycache__/schema.cpython-34.pyc
|
|
||||||
../sqlalchemy/sql/__pycache__/__init__.cpython-34.pyc
|
|
||||||
../sqlalchemy/sql/__pycache__/ddl.cpython-34.pyc
|
|
||||||
../sqlalchemy/sql/__pycache__/elements.cpython-34.pyc
|
|
||||||
../sqlalchemy/sql/__pycache__/compiler.cpython-34.pyc
|
|
||||||
../sqlalchemy/sql/__pycache__/annotation.cpython-34.pyc
|
|
||||||
../sqlalchemy/sql/__pycache__/dml.cpython-34.pyc
|
|
||||||
../sqlalchemy/sql/__pycache__/expression.cpython-34.pyc
|
|
||||||
../sqlalchemy/sql/__pycache__/operators.cpython-34.pyc
|
|
||||||
../sqlalchemy/sql/__pycache__/selectable.cpython-34.pyc
|
|
||||||
../sqlalchemy/sql/__pycache__/visitors.cpython-34.pyc
|
|
||||||
../sqlalchemy/sql/__pycache__/type_api.cpython-34.pyc
|
|
||||||
../sqlalchemy/sql/__pycache__/naming.cpython-34.pyc
|
|
||||||
../sqlalchemy/sql/__pycache__/util.cpython-34.pyc
|
|
||||||
../sqlalchemy/ext/__pycache__/serializer.cpython-34.pyc
|
|
||||||
../sqlalchemy/ext/__pycache__/associationproxy.cpython-34.pyc
|
|
||||||
../sqlalchemy/ext/__pycache__/automap.cpython-34.pyc
|
|
||||||
../sqlalchemy/ext/__pycache__/__init__.cpython-34.pyc
|
|
||||||
../sqlalchemy/ext/__pycache__/hybrid.cpython-34.pyc
|
|
||||||
../sqlalchemy/ext/__pycache__/compiler.cpython-34.pyc
|
|
||||||
../sqlalchemy/ext/__pycache__/horizontal_shard.cpython-34.pyc
|
|
||||||
../sqlalchemy/ext/__pycache__/orderinglist.cpython-34.pyc
|
|
||||||
../sqlalchemy/ext/__pycache__/instrumentation.cpython-34.pyc
|
|
||||||
../sqlalchemy/ext/__pycache__/mutable.cpython-34.pyc
|
|
||||||
../sqlalchemy/ext/declarative/__pycache__/base.cpython-34.pyc
|
|
||||||
../sqlalchemy/ext/declarative/__pycache__/__init__.cpython-34.pyc
|
|
||||||
../sqlalchemy/ext/declarative/__pycache__/clsregistry.cpython-34.pyc
|
|
||||||
../sqlalchemy/ext/declarative/__pycache__/api.cpython-34.pyc
|
|
||||||
../sqlalchemy/util/__pycache__/langhelpers.cpython-34.pyc
|
../sqlalchemy/util/__pycache__/langhelpers.cpython-34.pyc
|
||||||
../sqlalchemy/util/__pycache__/queue.cpython-34.pyc
|
../sqlalchemy/util/__pycache__/queue.cpython-34.pyc
|
||||||
../sqlalchemy/util/__pycache__/compat.cpython-34.pyc
|
|
||||||
../sqlalchemy/util/__pycache__/__init__.cpython-34.pyc
|
|
||||||
../sqlalchemy/util/__pycache__/deprecations.cpython-34.pyc
|
|
||||||
../sqlalchemy/util/__pycache__/_collections.cpython-34.pyc
|
|
||||||
../sqlalchemy/util/__pycache__/topological.cpython-34.pyc
|
../sqlalchemy/util/__pycache__/topological.cpython-34.pyc
|
||||||
../sqlalchemy/connectors/__pycache__/mxodbc.cpython-34.pyc
|
|
||||||
../sqlalchemy/connectors/__pycache__/__init__.cpython-34.pyc
|
|
||||||
../sqlalchemy/connectors/__pycache__/pyodbc.cpython-34.pyc
|
|
||||||
../sqlalchemy/connectors/__pycache__/mysqldb.cpython-34.pyc
|
|
||||||
../sqlalchemy/connectors/__pycache__/zxJDBC.cpython-34.pyc
|
|
||||||
../sqlalchemy/dialects/__pycache__/postgres.cpython-34.pyc
|
|
||||||
../sqlalchemy/dialects/__pycache__/__init__.cpython-34.pyc
|
|
||||||
../sqlalchemy/dialects/mssql/__pycache__/adodbapi.cpython-34.pyc
|
|
||||||
../sqlalchemy/dialects/mssql/__pycache__/mxodbc.cpython-34.pyc
|
|
||||||
../sqlalchemy/dialects/mssql/__pycache__/base.cpython-34.pyc
|
|
||||||
../sqlalchemy/dialects/mssql/__pycache__/information_schema.cpython-34.pyc
|
|
||||||
../sqlalchemy/dialects/mssql/__pycache__/__init__.cpython-34.pyc
|
|
||||||
../sqlalchemy/dialects/mssql/__pycache__/pyodbc.cpython-34.pyc
|
|
||||||
../sqlalchemy/dialects/mssql/__pycache__/zxjdbc.cpython-34.pyc
|
|
||||||
../sqlalchemy/dialects/mssql/__pycache__/pymssql.cpython-34.pyc
|
|
||||||
../sqlalchemy/dialects/postgresql/__pycache__/pg8000.cpython-34.pyc
|
|
||||||
../sqlalchemy/dialects/postgresql/__pycache__/ranges.cpython-34.pyc
|
|
||||||
../sqlalchemy/dialects/postgresql/__pycache__/base.cpython-34.pyc
|
|
||||||
../sqlalchemy/dialects/postgresql/__pycache__/__init__.cpython-34.pyc
|
|
||||||
../sqlalchemy/dialects/postgresql/__pycache__/zxjdbc.cpython-34.pyc
|
|
||||||
../sqlalchemy/dialects/postgresql/__pycache__/json.cpython-34.pyc
|
|
||||||
../sqlalchemy/dialects/postgresql/__pycache__/pypostgresql.cpython-34.pyc
|
|
||||||
../sqlalchemy/dialects/postgresql/__pycache__/constraints.cpython-34.pyc
|
|
||||||
../sqlalchemy/dialects/postgresql/__pycache__/hstore.cpython-34.pyc
|
|
||||||
../sqlalchemy/dialects/postgresql/__pycache__/psycopg2.cpython-34.pyc
|
|
||||||
../sqlalchemy/dialects/sybase/__pycache__/mxodbc.cpython-34.pyc
|
|
||||||
../sqlalchemy/dialects/sybase/__pycache__/base.cpython-34.pyc
|
|
||||||
../sqlalchemy/dialects/sybase/__pycache__/__init__.cpython-34.pyc
|
|
||||||
../sqlalchemy/dialects/sybase/__pycache__/pyodbc.cpython-34.pyc
|
|
||||||
../sqlalchemy/dialects/sybase/__pycache__/pysybase.cpython-34.pyc
|
|
||||||
../sqlalchemy/dialects/drizzle/__pycache__/base.cpython-34.pyc
|
|
||||||
../sqlalchemy/dialects/drizzle/__pycache__/__init__.cpython-34.pyc
|
|
||||||
../sqlalchemy/dialects/drizzle/__pycache__/mysqldb.cpython-34.pyc
|
|
||||||
../sqlalchemy/dialects/mysql/__pycache__/mysqlconnector.cpython-34.pyc
|
|
||||||
../sqlalchemy/dialects/mysql/__pycache__/base.cpython-34.pyc
|
|
||||||
../sqlalchemy/dialects/mysql/__pycache__/__init__.cpython-34.pyc
|
|
||||||
../sqlalchemy/dialects/mysql/__pycache__/pyodbc.cpython-34.pyc
|
|
||||||
../sqlalchemy/dialects/mysql/__pycache__/zxjdbc.cpython-34.pyc
|
|
||||||
../sqlalchemy/dialects/mysql/__pycache__/oursql.cpython-34.pyc
|
|
||||||
../sqlalchemy/dialects/mysql/__pycache__/pymysql.cpython-34.pyc
|
|
||||||
../sqlalchemy/dialects/mysql/__pycache__/cymysql.cpython-34.pyc
|
|
||||||
../sqlalchemy/dialects/mysql/__pycache__/gaerdbms.cpython-34.pyc
|
|
||||||
../sqlalchemy/dialects/mysql/__pycache__/mysqldb.cpython-34.pyc
|
|
||||||
../sqlalchemy/dialects/sqlite/__pycache__/base.cpython-34.pyc
|
|
||||||
../sqlalchemy/dialects/sqlite/__pycache__/__init__.cpython-34.pyc
|
|
||||||
../sqlalchemy/dialects/sqlite/__pycache__/pysqlite.cpython-34.pyc
|
|
||||||
../sqlalchemy/dialects/firebird/__pycache__/base.cpython-34.pyc
|
|
||||||
../sqlalchemy/dialects/firebird/__pycache__/__init__.cpython-34.pyc
|
|
||||||
../sqlalchemy/dialects/firebird/__pycache__/fdb.cpython-34.pyc
|
|
||||||
../sqlalchemy/dialects/firebird/__pycache__/kinterbasdb.cpython-34.pyc
|
|
||||||
../sqlalchemy/dialects/oracle/__pycache__/base.cpython-34.pyc
|
|
||||||
../sqlalchemy/dialects/oracle/__pycache__/__init__.cpython-34.pyc
|
|
||||||
../sqlalchemy/dialects/oracle/__pycache__/zxjdbc.cpython-34.pyc
|
|
||||||
../sqlalchemy/dialects/oracle/__pycache__/cx_oracle.cpython-34.pyc
|
|
||||||
../sqlalchemy/engine/__pycache__/interfaces.cpython-34.pyc
|
|
||||||
../sqlalchemy/engine/__pycache__/result.cpython-34.pyc
|
|
||||||
../sqlalchemy/engine/__pycache__/base.cpython-34.pyc
|
|
||||||
../sqlalchemy/engine/__pycache__/url.cpython-34.pyc
|
|
||||||
../sqlalchemy/engine/__pycache__/threadlocal.cpython-34.pyc
|
|
||||||
../sqlalchemy/engine/__pycache__/__init__.cpython-34.pyc
|
|
||||||
../sqlalchemy/engine/__pycache__/default.cpython-34.pyc
|
|
||||||
../sqlalchemy/engine/__pycache__/strategies.cpython-34.pyc
|
|
||||||
../sqlalchemy/engine/__pycache__/reflection.cpython-34.pyc
|
|
||||||
../sqlalchemy/engine/__pycache__/util.cpython-34.pyc
|
|
||||||
../sqlalchemy/event/__pycache__/base.cpython-34.pyc
|
|
||||||
../sqlalchemy/event/__pycache__/__init__.cpython-34.pyc
|
|
||||||
../sqlalchemy/event/__pycache__/attr.cpython-34.pyc
|
|
||||||
../sqlalchemy/event/__pycache__/registry.cpython-34.pyc
|
|
||||||
../sqlalchemy/event/__pycache__/legacy.cpython-34.pyc
|
|
||||||
../sqlalchemy/event/__pycache__/api.cpython-34.pyc
|
|
||||||
../sqlalchemy/cprocessors.cpython-34m.so
|
../sqlalchemy/cprocessors.cpython-34m.so
|
||||||
../sqlalchemy/cresultproxy.cpython-34m.so
|
../sqlalchemy/cresultproxy.cpython-34m.so
|
||||||
../sqlalchemy/cutils.cpython-34m.so
|
../sqlalchemy/cutils.cpython-34m.so
|
||||||
|
|
Binary file not shown.
|
@ -1,104 +0,0 @@
|
||||||
LICENSE
|
|
||||||
MANIFEST.in
|
|
||||||
setup.cfg
|
|
||||||
setup.py
|
|
||||||
setup_base.py
|
|
||||||
c/_cffi_backend.c
|
|
||||||
c/file_emulator.h
|
|
||||||
c/malloc_closure.h
|
|
||||||
c/minibuffer.h
|
|
||||||
c/misc_thread.h
|
|
||||||
c/misc_win32.h
|
|
||||||
c/test_c.py
|
|
||||||
c/wchar_helper.h
|
|
||||||
c/libffi_msvc/ffi.c
|
|
||||||
c/libffi_msvc/ffi.h
|
|
||||||
c/libffi_msvc/ffi_common.h
|
|
||||||
c/libffi_msvc/fficonfig.h
|
|
||||||
c/libffi_msvc/ffitarget.h
|
|
||||||
c/libffi_msvc/prep_cif.c
|
|
||||||
c/libffi_msvc/types.c
|
|
||||||
c/libffi_msvc/win32.c
|
|
||||||
c/libffi_msvc/win64.asm
|
|
||||||
c/libffi_msvc/win64.obj
|
|
||||||
cffi/__init__.py
|
|
||||||
cffi/api.py
|
|
||||||
cffi/backend_ctypes.py
|
|
||||||
cffi/commontypes.py
|
|
||||||
cffi/cparser.py
|
|
||||||
cffi/ffiplatform.py
|
|
||||||
cffi/gc_weakref.py
|
|
||||||
cffi/lock.py
|
|
||||||
cffi/model.py
|
|
||||||
cffi/vengine_cpy.py
|
|
||||||
cffi/vengine_gen.py
|
|
||||||
cffi/verifier.py
|
|
||||||
cffi.egg-info/PKG-INFO
|
|
||||||
cffi.egg-info/SOURCES.txt
|
|
||||||
cffi.egg-info/dependency_links.txt
|
|
||||||
cffi.egg-info/not-zip-safe
|
|
||||||
cffi.egg-info/requires.txt
|
|
||||||
cffi.egg-info/top_level.txt
|
|
||||||
demo/_curses.py
|
|
||||||
demo/api.py
|
|
||||||
demo/bsdopendirtype.py
|
|
||||||
demo/btrfs-snap.py
|
|
||||||
demo/cffi-cocoa.py
|
|
||||||
demo/fastcsv.py
|
|
||||||
demo/gmp.py
|
|
||||||
demo/pwuid.py
|
|
||||||
demo/py.cleanup
|
|
||||||
demo/pyobj.py
|
|
||||||
demo/readdir.py
|
|
||||||
demo/readdir2.py
|
|
||||||
demo/readdir_ctypes.py
|
|
||||||
demo/setup.py
|
|
||||||
demo/winclipboard.py
|
|
||||||
demo/xclient.py
|
|
||||||
doc/Makefile
|
|
||||||
doc/design.rst
|
|
||||||
doc/make.bat
|
|
||||||
doc/source/conf.py
|
|
||||||
doc/source/index.rst
|
|
||||||
testing/__init__.py
|
|
||||||
testing/backend_tests.py
|
|
||||||
testing/callback_in_thread.py
|
|
||||||
testing/support.py
|
|
||||||
testing/test_cdata.py
|
|
||||||
testing/test_ctypes.py
|
|
||||||
testing/test_ffi_backend.py
|
|
||||||
testing/test_function.py
|
|
||||||
testing/test_model.py
|
|
||||||
testing/test_ownlib.py
|
|
||||||
testing/test_parsing.py
|
|
||||||
testing/test_platform.py
|
|
||||||
testing/test_unicode_literals.py
|
|
||||||
testing/test_verify.py
|
|
||||||
testing/test_verify2.py
|
|
||||||
testing/test_version.py
|
|
||||||
testing/test_vgen.py
|
|
||||||
testing/test_vgen2.py
|
|
||||||
testing/test_zdistutils.py
|
|
||||||
testing/test_zintegration.py
|
|
||||||
testing/udir.py
|
|
||||||
testing/snippets/distutils_module/setup.py
|
|
||||||
testing/snippets/distutils_module/snip_basic_verify.py
|
|
||||||
testing/snippets/distutils_module/build/lib.linux-x86_64-2.7/snip_basic_verify.py
|
|
||||||
testing/snippets/distutils_package_1/setup.py
|
|
||||||
testing/snippets/distutils_package_1/build/lib.linux-x86_64-2.7/snip_basic_verify1/__init__.py
|
|
||||||
testing/snippets/distutils_package_1/snip_basic_verify1/__init__.py
|
|
||||||
testing/snippets/distutils_package_2/setup.py
|
|
||||||
testing/snippets/distutils_package_2/build/lib.linux-x86_64-2.7/snip_basic_verify2/__init__.py
|
|
||||||
testing/snippets/distutils_package_2/snip_basic_verify2/__init__.py
|
|
||||||
testing/snippets/infrastructure/setup.py
|
|
||||||
testing/snippets/infrastructure/build/lib.linux-x86_64-2.7/snip_infrastructure/__init__.py
|
|
||||||
testing/snippets/infrastructure/snip_infrastructure/__init__.py
|
|
||||||
testing/snippets/setuptools_module/setup.py
|
|
||||||
testing/snippets/setuptools_module/snip_setuptools_verify.py
|
|
||||||
testing/snippets/setuptools_module/build/lib.linux-x86_64-2.7/snip_setuptools_verify.py
|
|
||||||
testing/snippets/setuptools_package_1/setup.py
|
|
||||||
testing/snippets/setuptools_package_1/build/lib.linux-x86_64-2.7/snip_setuptools_verify1/__init__.py
|
|
||||||
testing/snippets/setuptools_package_1/snip_setuptools_verify1/__init__.py
|
|
||||||
testing/snippets/setuptools_package_2/setup.py
|
|
||||||
testing/snippets/setuptools_package_2/build/lib.linux-x86_64-2.7/snip_setuptools_verify2/__init__.py
|
|
||||||
testing/snippets/setuptools_package_2/snip_setuptools_verify2/__init__.py
|
|
|
@ -1,6 +1,6 @@
|
||||||
Metadata-Version: 1.1
|
Metadata-Version: 1.1
|
||||||
Name: cffi
|
Name: cffi
|
||||||
Version: 0.8.6
|
Version: 1.3.0
|
||||||
Summary: Foreign Function Interface for Python calling C code.
|
Summary: Foreign Function Interface for Python calling C code.
|
||||||
Home-page: http://cffi.readthedocs.org
|
Home-page: http://cffi.readthedocs.org
|
||||||
Author: Armin Rigo, Maciej Fijalkowski
|
Author: Armin Rigo, Maciej Fijalkowski
|
||||||
|
@ -26,3 +26,6 @@ Classifier: Programming Language :: Python :: 2.7
|
||||||
Classifier: Programming Language :: Python :: 3
|
Classifier: Programming Language :: Python :: 3
|
||||||
Classifier: Programming Language :: Python :: 3.2
|
Classifier: Programming Language :: Python :: 3.2
|
||||||
Classifier: Programming Language :: Python :: 3.3
|
Classifier: Programming Language :: Python :: 3.3
|
||||||
|
Classifier: Programming Language :: Python :: 3.4
|
||||||
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
||||||
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
@ -0,0 +1,145 @@
|
||||||
|
AUTHORS
|
||||||
|
LICENSE
|
||||||
|
MANIFEST.in
|
||||||
|
setup.cfg
|
||||||
|
setup.py
|
||||||
|
setup_base.py
|
||||||
|
c/_cffi_backend.c
|
||||||
|
c/cdlopen.c
|
||||||
|
c/cffi1_module.c
|
||||||
|
c/cglob.c
|
||||||
|
c/ffi_obj.c
|
||||||
|
c/file_emulator.h
|
||||||
|
c/lib_obj.c
|
||||||
|
c/malloc_closure.h
|
||||||
|
c/minibuffer.h
|
||||||
|
c/misc_thread.h
|
||||||
|
c/misc_win32.h
|
||||||
|
c/parse_c_type.c
|
||||||
|
c/realize_c_type.c
|
||||||
|
c/test_c.py
|
||||||
|
c/wchar_helper.h
|
||||||
|
c/libffi_msvc/ffi.c
|
||||||
|
c/libffi_msvc/ffi.h
|
||||||
|
c/libffi_msvc/ffi_common.h
|
||||||
|
c/libffi_msvc/fficonfig.h
|
||||||
|
c/libffi_msvc/ffitarget.h
|
||||||
|
c/libffi_msvc/prep_cif.c
|
||||||
|
c/libffi_msvc/types.c
|
||||||
|
c/libffi_msvc/win32.c
|
||||||
|
c/libffi_msvc/win64.asm
|
||||||
|
c/libffi_msvc/win64.obj
|
||||||
|
cffi/__init__.py
|
||||||
|
cffi/_cffi_include.h
|
||||||
|
cffi/api.py
|
||||||
|
cffi/backend_ctypes.py
|
||||||
|
cffi/cffi_opcode.py
|
||||||
|
cffi/commontypes.py
|
||||||
|
cffi/cparser.py
|
||||||
|
cffi/ffiplatform.py
|
||||||
|
cffi/gc_weakref.py
|
||||||
|
cffi/lock.py
|
||||||
|
cffi/model.py
|
||||||
|
cffi/parse_c_type.h
|
||||||
|
cffi/recompiler.py
|
||||||
|
cffi/setuptools_ext.py
|
||||||
|
cffi/vengine_cpy.py
|
||||||
|
cffi/vengine_gen.py
|
||||||
|
cffi/verifier.py
|
||||||
|
cffi.egg-info/PKG-INFO
|
||||||
|
cffi.egg-info/SOURCES.txt
|
||||||
|
cffi.egg-info/dependency_links.txt
|
||||||
|
cffi.egg-info/entry_points.txt
|
||||||
|
cffi.egg-info/not-zip-safe
|
||||||
|
cffi.egg-info/requires.txt
|
||||||
|
cffi.egg-info/top_level.txt
|
||||||
|
demo/_curses.py
|
||||||
|
demo/_curses_build.py
|
||||||
|
demo/_curses_setup.py
|
||||||
|
demo/api.py
|
||||||
|
demo/bsdopendirtype.py
|
||||||
|
demo/bsdopendirtype_build.py
|
||||||
|
demo/bsdopendirtype_setup.py
|
||||||
|
demo/btrfs-snap.py
|
||||||
|
demo/cffi-cocoa.py
|
||||||
|
demo/fastcsv.py
|
||||||
|
demo/gmp.py
|
||||||
|
demo/manual.c
|
||||||
|
demo/manual2.py
|
||||||
|
demo/pwuid.py
|
||||||
|
demo/py.cleanup
|
||||||
|
demo/pyobj.py
|
||||||
|
demo/readdir.py
|
||||||
|
demo/readdir2.py
|
||||||
|
demo/readdir2_build.py
|
||||||
|
demo/readdir2_setup.py
|
||||||
|
demo/readdir_build.py
|
||||||
|
demo/readdir_ctypes.py
|
||||||
|
demo/readdir_setup.py
|
||||||
|
demo/recopendirtype.py
|
||||||
|
demo/recopendirtype_build.py
|
||||||
|
demo/setup.py
|
||||||
|
demo/setup_manual.py
|
||||||
|
demo/winclipboard.py
|
||||||
|
demo/xclient.py
|
||||||
|
doc/Makefile
|
||||||
|
doc/make.bat
|
||||||
|
doc/misc/design.rst
|
||||||
|
doc/misc/grant-cffi-1.0.rst
|
||||||
|
doc/misc/parse_c_type.rst
|
||||||
|
doc/source/cdef.rst
|
||||||
|
doc/source/conf.py
|
||||||
|
doc/source/index.rst
|
||||||
|
doc/source/installation.rst
|
||||||
|
doc/source/overview.rst
|
||||||
|
doc/source/using.rst
|
||||||
|
doc/source/whatsnew.rst
|
||||||
|
testing/__init__.py
|
||||||
|
testing/support.py
|
||||||
|
testing/udir.py
|
||||||
|
testing/cffi0/__init__.py
|
||||||
|
testing/cffi0/backend_tests.py
|
||||||
|
testing/cffi0/callback_in_thread.py
|
||||||
|
testing/cffi0/test_cdata.py
|
||||||
|
testing/cffi0/test_ctypes.py
|
||||||
|
testing/cffi0/test_ffi_backend.py
|
||||||
|
testing/cffi0/test_function.py
|
||||||
|
testing/cffi0/test_model.py
|
||||||
|
testing/cffi0/test_ownlib.py
|
||||||
|
testing/cffi0/test_parsing.py
|
||||||
|
testing/cffi0/test_platform.py
|
||||||
|
testing/cffi0/test_unicode_literals.py
|
||||||
|
testing/cffi0/test_verify.py
|
||||||
|
testing/cffi0/test_verify2.py
|
||||||
|
testing/cffi0/test_version.py
|
||||||
|
testing/cffi0/test_vgen.py
|
||||||
|
testing/cffi0/test_vgen2.py
|
||||||
|
testing/cffi0/test_zdistutils.py
|
||||||
|
testing/cffi0/test_zintegration.py
|
||||||
|
testing/cffi0/snippets/distutils_module/setup.py
|
||||||
|
testing/cffi0/snippets/distutils_module/snip_basic_verify.py
|
||||||
|
testing/cffi0/snippets/distutils_package_1/setup.py
|
||||||
|
testing/cffi0/snippets/distutils_package_1/snip_basic_verify1/__init__.py
|
||||||
|
testing/cffi0/snippets/distutils_package_2/setup.py
|
||||||
|
testing/cffi0/snippets/distutils_package_2/snip_basic_verify2/__init__.py
|
||||||
|
testing/cffi0/snippets/infrastructure/setup.py
|
||||||
|
testing/cffi0/snippets/infrastructure/snip_infrastructure/__init__.py
|
||||||
|
testing/cffi0/snippets/setuptools_module/setup.py
|
||||||
|
testing/cffi0/snippets/setuptools_module/snip_setuptools_verify.py
|
||||||
|
testing/cffi0/snippets/setuptools_package_1/setup.py
|
||||||
|
testing/cffi0/snippets/setuptools_package_1/snip_setuptools_verify1/__init__.py
|
||||||
|
testing/cffi0/snippets/setuptools_package_2/setup.py
|
||||||
|
testing/cffi0/snippets/setuptools_package_2/snip_setuptools_verify2/__init__.py
|
||||||
|
testing/cffi1/__init__.py
|
||||||
|
testing/cffi1/test_cffi_binary.py
|
||||||
|
testing/cffi1/test_dlopen.py
|
||||||
|
testing/cffi1/test_dlopen_unicode_literals.py
|
||||||
|
testing/cffi1/test_ffi_obj.py
|
||||||
|
testing/cffi1/test_new_ffi_1.py
|
||||||
|
testing/cffi1/test_parse_c_type.py
|
||||||
|
testing/cffi1/test_re_python.py
|
||||||
|
testing/cffi1/test_realize_c_type.py
|
||||||
|
testing/cffi1/test_recompiler.py
|
||||||
|
testing/cffi1/test_unicode_literals.py
|
||||||
|
testing/cffi1/test_verify1.py
|
||||||
|
testing/cffi1/test_zdist.py
|
|
@ -0,0 +1,3 @@
|
||||||
|
[distutils.setup_keywords]
|
||||||
|
cffi_modules = cffi.setuptools_ext:cffi_modules
|
||||||
|
|
|
@ -1,32 +1,41 @@
|
||||||
../cffi/lock.py
|
|
||||||
../cffi/backend_ctypes.py
|
|
||||||
../cffi/__init__.py
|
|
||||||
../cffi/ffiplatform.py
|
|
||||||
../cffi/vengine_gen.py
|
|
||||||
../cffi/commontypes.py
|
|
||||||
../cffi/vengine_cpy.py
|
|
||||||
../cffi/api.py
|
|
||||||
../cffi/gc_weakref.py
|
../cffi/gc_weakref.py
|
||||||
|
../cffi/recompiler.py
|
||||||
../cffi/verifier.py
|
../cffi/verifier.py
|
||||||
|
../cffi/backend_ctypes.py
|
||||||
|
../cffi/api.py
|
||||||
|
../cffi/ffiplatform.py
|
||||||
../cffi/cparser.py
|
../cffi/cparser.py
|
||||||
|
../cffi/vengine_cpy.py
|
||||||
|
../cffi/lock.py
|
||||||
|
../cffi/cffi_opcode.py
|
||||||
|
../cffi/setuptools_ext.py
|
||||||
|
../cffi/vengine_gen.py
|
||||||
../cffi/model.py
|
../cffi/model.py
|
||||||
../cffi/__pycache__/lock.cpython-34.pyc
|
../cffi/__init__.py
|
||||||
../cffi/__pycache__/backend_ctypes.cpython-34.pyc
|
../cffi/commontypes.py
|
||||||
../cffi/__pycache__/__init__.cpython-34.pyc
|
../cffi/_cffi_include.h
|
||||||
../cffi/__pycache__/ffiplatform.cpython-34.pyc
|
../cffi/parse_c_type.h
|
||||||
../cffi/__pycache__/vengine_gen.cpython-34.pyc
|
|
||||||
../cffi/__pycache__/commontypes.cpython-34.pyc
|
|
||||||
../cffi/__pycache__/vengine_cpy.cpython-34.pyc
|
|
||||||
../cffi/__pycache__/api.cpython-34.pyc
|
|
||||||
../cffi/__pycache__/gc_weakref.cpython-34.pyc
|
../cffi/__pycache__/gc_weakref.cpython-34.pyc
|
||||||
|
../cffi/__pycache__/recompiler.cpython-34.pyc
|
||||||
../cffi/__pycache__/verifier.cpython-34.pyc
|
../cffi/__pycache__/verifier.cpython-34.pyc
|
||||||
|
../cffi/__pycache__/backend_ctypes.cpython-34.pyc
|
||||||
|
../cffi/__pycache__/api.cpython-34.pyc
|
||||||
|
../cffi/__pycache__/ffiplatform.cpython-34.pyc
|
||||||
../cffi/__pycache__/cparser.cpython-34.pyc
|
../cffi/__pycache__/cparser.cpython-34.pyc
|
||||||
|
../cffi/__pycache__/vengine_cpy.cpython-34.pyc
|
||||||
|
../cffi/__pycache__/lock.cpython-34.pyc
|
||||||
|
../cffi/__pycache__/cffi_opcode.cpython-34.pyc
|
||||||
|
../cffi/__pycache__/setuptools_ext.cpython-34.pyc
|
||||||
|
../cffi/__pycache__/vengine_gen.cpython-34.pyc
|
||||||
../cffi/__pycache__/model.cpython-34.pyc
|
../cffi/__pycache__/model.cpython-34.pyc
|
||||||
|
../cffi/__pycache__/__init__.cpython-34.pyc
|
||||||
|
../cffi/__pycache__/commontypes.cpython-34.pyc
|
||||||
../_cffi_backend.cpython-34m.so
|
../_cffi_backend.cpython-34m.so
|
||||||
./
|
./
|
||||||
dependency_links.txt
|
|
||||||
PKG-INFO
|
PKG-INFO
|
||||||
SOURCES.txt
|
SOURCES.txt
|
||||||
|
entry_points.txt
|
||||||
not-zip-safe
|
not-zip-safe
|
||||||
top_level.txt
|
dependency_links.txt
|
||||||
requires.txt
|
requires.txt
|
||||||
|
top_level.txt
|
|
@ -1,2 +1,2 @@
|
||||||
cffi
|
|
||||||
_cffi_backend
|
_cffi_backend
|
||||||
|
cffi
|
|
@ -4,5 +4,10 @@ __all__ = ['FFI', 'VerificationError', 'VerificationMissing', 'CDefError',
|
||||||
from .api import FFI, CDefError, FFIError
|
from .api import FFI, CDefError, FFIError
|
||||||
from .ffiplatform import VerificationError, VerificationMissing
|
from .ffiplatform import VerificationError, VerificationMissing
|
||||||
|
|
||||||
__version__ = "0.8.6"
|
__version__ = "1.3.0"
|
||||||
__version_info__ = (0, 8, 6)
|
__version_info__ = (1, 3, 0)
|
||||||
|
|
||||||
|
# The verifier module file names are based on the CRC32 of a string that
|
||||||
|
# contains the following version number. It may be older than __version__
|
||||||
|
# if nothing is clearly incompatible.
|
||||||
|
__version_verifier_modules__ = "0.8.6"
|
||||||
|
|
229
Linux_x86_64/lib/python3.4/site-packages/cffi/_cffi_include.h
Normal file
229
Linux_x86_64/lib/python3.4/site-packages/cffi/_cffi_include.h
Normal file
|
@ -0,0 +1,229 @@
|
||||||
|
#define _CFFI_
|
||||||
|
#include <Python.h>
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
#include <stddef.h>
|
||||||
|
#include "parse_c_type.h"
|
||||||
|
|
||||||
|
/* this block of #ifs should be kept exactly identical between
|
||||||
|
c/_cffi_backend.c, cffi/vengine_cpy.py, cffi/vengine_gen.py
|
||||||
|
and cffi/_cffi_include.h */
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
# include <malloc.h> /* for alloca() */
|
||||||
|
# if _MSC_VER < 1600 /* MSVC < 2010 */
|
||||||
|
typedef __int8 int8_t;
|
||||||
|
typedef __int16 int16_t;
|
||||||
|
typedef __int32 int32_t;
|
||||||
|
typedef __int64 int64_t;
|
||||||
|
typedef unsigned __int8 uint8_t;
|
||||||
|
typedef unsigned __int16 uint16_t;
|
||||||
|
typedef unsigned __int32 uint32_t;
|
||||||
|
typedef unsigned __int64 uint64_t;
|
||||||
|
typedef __int8 int_least8_t;
|
||||||
|
typedef __int16 int_least16_t;
|
||||||
|
typedef __int32 int_least32_t;
|
||||||
|
typedef __int64 int_least64_t;
|
||||||
|
typedef unsigned __int8 uint_least8_t;
|
||||||
|
typedef unsigned __int16 uint_least16_t;
|
||||||
|
typedef unsigned __int32 uint_least32_t;
|
||||||
|
typedef unsigned __int64 uint_least64_t;
|
||||||
|
typedef __int8 int_fast8_t;
|
||||||
|
typedef __int16 int_fast16_t;
|
||||||
|
typedef __int32 int_fast32_t;
|
||||||
|
typedef __int64 int_fast64_t;
|
||||||
|
typedef unsigned __int8 uint_fast8_t;
|
||||||
|
typedef unsigned __int16 uint_fast16_t;
|
||||||
|
typedef unsigned __int32 uint_fast32_t;
|
||||||
|
typedef unsigned __int64 uint_fast64_t;
|
||||||
|
typedef __int64 intmax_t;
|
||||||
|
typedef unsigned __int64 uintmax_t;
|
||||||
|
# else
|
||||||
|
# include <stdint.h>
|
||||||
|
# endif
|
||||||
|
# if _MSC_VER < 1800 /* MSVC < 2013 */
|
||||||
|
typedef unsigned char _Bool;
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
# include <stdint.h>
|
||||||
|
# if (defined (__SVR4) && defined (__sun)) || defined(_AIX) || defined(__hpux)
|
||||||
|
# include <alloca.h>
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
# define _CFFI_UNUSED_FN __attribute__((unused))
|
||||||
|
#else
|
||||||
|
# define _CFFI_UNUSED_FN /* nothing */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/********** CPython-specific section **********/
|
||||||
|
#ifndef PYPY_VERSION
|
||||||
|
|
||||||
|
|
||||||
|
#if PY_MAJOR_VERSION >= 3
|
||||||
|
# define PyInt_FromLong PyLong_FromLong
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define _cffi_from_c_double PyFloat_FromDouble
|
||||||
|
#define _cffi_from_c_float PyFloat_FromDouble
|
||||||
|
#define _cffi_from_c_long PyInt_FromLong
|
||||||
|
#define _cffi_from_c_ulong PyLong_FromUnsignedLong
|
||||||
|
#define _cffi_from_c_longlong PyLong_FromLongLong
|
||||||
|
#define _cffi_from_c_ulonglong PyLong_FromUnsignedLongLong
|
||||||
|
|
||||||
|
#define _cffi_to_c_double PyFloat_AsDouble
|
||||||
|
#define _cffi_to_c_float PyFloat_AsDouble
|
||||||
|
|
||||||
|
#define _cffi_from_c_int(x, type) \
|
||||||
|
(((type)-1) > 0 ? /* unsigned */ \
|
||||||
|
(sizeof(type) < sizeof(long) ? \
|
||||||
|
PyInt_FromLong((long)x) : \
|
||||||
|
sizeof(type) == sizeof(long) ? \
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)x) : \
|
||||||
|
PyLong_FromUnsignedLongLong((unsigned long long)x)) : \
|
||||||
|
(sizeof(type) <= sizeof(long) ? \
|
||||||
|
PyInt_FromLong((long)x) : \
|
||||||
|
PyLong_FromLongLong((long long)x)))
|
||||||
|
|
||||||
|
#define _cffi_to_c_int(o, type) \
|
||||||
|
((type)( \
|
||||||
|
sizeof(type) == 1 ? (((type)-1) > 0 ? (type)_cffi_to_c_u8(o) \
|
||||||
|
: (type)_cffi_to_c_i8(o)) : \
|
||||||
|
sizeof(type) == 2 ? (((type)-1) > 0 ? (type)_cffi_to_c_u16(o) \
|
||||||
|
: (type)_cffi_to_c_i16(o)) : \
|
||||||
|
sizeof(type) == 4 ? (((type)-1) > 0 ? (type)_cffi_to_c_u32(o) \
|
||||||
|
: (type)_cffi_to_c_i32(o)) : \
|
||||||
|
sizeof(type) == 8 ? (((type)-1) > 0 ? (type)_cffi_to_c_u64(o) \
|
||||||
|
: (type)_cffi_to_c_i64(o)) : \
|
||||||
|
(Py_FatalError("unsupported size for type " #type), (type)0)))
|
||||||
|
|
||||||
|
#define _cffi_to_c_i8 \
|
||||||
|
((int(*)(PyObject *))_cffi_exports[1])
|
||||||
|
#define _cffi_to_c_u8 \
|
||||||
|
((int(*)(PyObject *))_cffi_exports[2])
|
||||||
|
#define _cffi_to_c_i16 \
|
||||||
|
((int(*)(PyObject *))_cffi_exports[3])
|
||||||
|
#define _cffi_to_c_u16 \
|
||||||
|
((int(*)(PyObject *))_cffi_exports[4])
|
||||||
|
#define _cffi_to_c_i32 \
|
||||||
|
((int(*)(PyObject *))_cffi_exports[5])
|
||||||
|
#define _cffi_to_c_u32 \
|
||||||
|
((unsigned int(*)(PyObject *))_cffi_exports[6])
|
||||||
|
#define _cffi_to_c_i64 \
|
||||||
|
((long long(*)(PyObject *))_cffi_exports[7])
|
||||||
|
#define _cffi_to_c_u64 \
|
||||||
|
((unsigned long long(*)(PyObject *))_cffi_exports[8])
|
||||||
|
#define _cffi_to_c_char \
|
||||||
|
((int(*)(PyObject *))_cffi_exports[9])
|
||||||
|
#define _cffi_from_c_pointer \
|
||||||
|
((PyObject *(*)(char *, CTypeDescrObject *))_cffi_exports[10])
|
||||||
|
#define _cffi_to_c_pointer \
|
||||||
|
((char *(*)(PyObject *, CTypeDescrObject *))_cffi_exports[11])
|
||||||
|
#define _cffi_get_struct_layout \
|
||||||
|
not used any more
|
||||||
|
#define _cffi_restore_errno \
|
||||||
|
((void(*)(void))_cffi_exports[13])
|
||||||
|
#define _cffi_save_errno \
|
||||||
|
((void(*)(void))_cffi_exports[14])
|
||||||
|
#define _cffi_from_c_char \
|
||||||
|
((PyObject *(*)(char))_cffi_exports[15])
|
||||||
|
#define _cffi_from_c_deref \
|
||||||
|
((PyObject *(*)(char *, CTypeDescrObject *))_cffi_exports[16])
|
||||||
|
#define _cffi_to_c \
|
||||||
|
((int(*)(char *, CTypeDescrObject *, PyObject *))_cffi_exports[17])
|
||||||
|
#define _cffi_from_c_struct \
|
||||||
|
((PyObject *(*)(char *, CTypeDescrObject *))_cffi_exports[18])
|
||||||
|
#define _cffi_to_c_wchar_t \
|
||||||
|
((wchar_t(*)(PyObject *))_cffi_exports[19])
|
||||||
|
#define _cffi_from_c_wchar_t \
|
||||||
|
((PyObject *(*)(wchar_t))_cffi_exports[20])
|
||||||
|
#define _cffi_to_c_long_double \
|
||||||
|
((long double(*)(PyObject *))_cffi_exports[21])
|
||||||
|
#define _cffi_to_c__Bool \
|
||||||
|
((_Bool(*)(PyObject *))_cffi_exports[22])
|
||||||
|
#define _cffi_prepare_pointer_call_argument \
|
||||||
|
((Py_ssize_t(*)(CTypeDescrObject *, PyObject *, char **))_cffi_exports[23])
|
||||||
|
#define _cffi_convert_array_from_object \
|
||||||
|
((int(*)(char *, CTypeDescrObject *, PyObject *))_cffi_exports[24])
|
||||||
|
#define _CFFI_NUM_EXPORTS 25
|
||||||
|
|
||||||
|
typedef struct _ctypedescr CTypeDescrObject;
|
||||||
|
|
||||||
|
static void *_cffi_exports[_CFFI_NUM_EXPORTS];
|
||||||
|
|
||||||
|
#define _cffi_type(index) ( \
|
||||||
|
assert((((uintptr_t)_cffi_types[index]) & 1) == 0), \
|
||||||
|
(CTypeDescrObject *)_cffi_types[index])
|
||||||
|
|
||||||
|
static PyObject *_cffi_init(const char *module_name, Py_ssize_t version,
|
||||||
|
const struct _cffi_type_context_s *ctx)
|
||||||
|
{
|
||||||
|
PyObject *module, *o_arg, *new_module;
|
||||||
|
void *raw[] = {
|
||||||
|
(void *)module_name,
|
||||||
|
(void *)version,
|
||||||
|
(void *)_cffi_exports,
|
||||||
|
(void *)ctx,
|
||||||
|
};
|
||||||
|
|
||||||
|
module = PyImport_ImportModule("_cffi_backend");
|
||||||
|
if (module == NULL)
|
||||||
|
goto failure;
|
||||||
|
|
||||||
|
o_arg = PyLong_FromVoidPtr((void *)raw);
|
||||||
|
if (o_arg == NULL)
|
||||||
|
goto failure;
|
||||||
|
|
||||||
|
new_module = PyObject_CallMethod(
|
||||||
|
module, (char *)"_init_cffi_1_0_external_module", (char *)"O", o_arg);
|
||||||
|
|
||||||
|
Py_DECREF(o_arg);
|
||||||
|
Py_DECREF(module);
|
||||||
|
return new_module;
|
||||||
|
|
||||||
|
failure:
|
||||||
|
Py_XDECREF(module);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
_CFFI_UNUSED_FN
|
||||||
|
static PyObject **_cffi_unpack_args(PyObject *args_tuple, Py_ssize_t expected,
|
||||||
|
const char *fnname)
|
||||||
|
{
|
||||||
|
if (PyTuple_GET_SIZE(args_tuple) != expected) {
|
||||||
|
PyErr_Format(PyExc_TypeError,
|
||||||
|
"%.150s() takes exactly %zd arguments (%zd given)",
|
||||||
|
fnname, expected, PyTuple_GET_SIZE(args_tuple));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return &PyTuple_GET_ITEM(args_tuple, 0); /* pointer to the first item,
|
||||||
|
the others follow */
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
/********** end CPython-specific section **********/
|
||||||
|
|
||||||
|
|
||||||
|
#define _cffi_array_len(array) (sizeof(array) / sizeof((array)[0]))
|
||||||
|
|
||||||
|
#define _cffi_prim_int(size, sign) \
|
||||||
|
((size) == 1 ? ((sign) ? _CFFI_PRIM_INT8 : _CFFI_PRIM_UINT8) : \
|
||||||
|
(size) == 2 ? ((sign) ? _CFFI_PRIM_INT16 : _CFFI_PRIM_UINT16) : \
|
||||||
|
(size) == 4 ? ((sign) ? _CFFI_PRIM_INT32 : _CFFI_PRIM_UINT32) : \
|
||||||
|
(size) == 8 ? ((sign) ? _CFFI_PRIM_INT64 : _CFFI_PRIM_UINT64) : \
|
||||||
|
_CFFI__UNKNOWN_PRIM)
|
||||||
|
|
||||||
|
#define _cffi_prim_float(size) \
|
||||||
|
((size) == sizeof(float) ? _CFFI_PRIM_FLOAT : \
|
||||||
|
(size) == sizeof(double) ? _CFFI_PRIM_DOUBLE : \
|
||||||
|
(size) == sizeof(long double) ? _CFFI__UNKNOWN_LONG_DOUBLE : \
|
||||||
|
_CFFI__UNKNOWN_FLOAT_PRIM)
|
||||||
|
|
||||||
|
#define _cffi_check_int(got, got_nonpos, expected) \
|
||||||
|
((got_nonpos) == (expected <= 0) && \
|
||||||
|
(got) == (unsigned long long)expected)
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -55,7 +55,8 @@ class FFI(object):
|
||||||
# _cffi_backend.so compiled.
|
# _cffi_backend.so compiled.
|
||||||
import _cffi_backend as backend
|
import _cffi_backend as backend
|
||||||
from . import __version__
|
from . import __version__
|
||||||
assert backend.__version__ == __version__
|
assert backend.__version__ == __version__, \
|
||||||
|
"version mismatch, %s != %s" % (backend.__version__, __version__)
|
||||||
# (If you insist you can also try to pass the option
|
# (If you insist you can also try to pass the option
|
||||||
# 'backend=backend_ctypes.CTypesBackend()', but don't
|
# 'backend=backend_ctypes.CTypesBackend()', but don't
|
||||||
# rely on it! It's probably not going to work well.)
|
# rely on it! It's probably not going to work well.)
|
||||||
|
@ -69,6 +70,8 @@ class FFI(object):
|
||||||
self._function_caches = []
|
self._function_caches = []
|
||||||
self._libraries = []
|
self._libraries = []
|
||||||
self._cdefsources = []
|
self._cdefsources = []
|
||||||
|
self._included_ffis = []
|
||||||
|
self._windows_unicode = None
|
||||||
if hasattr(backend, 'set_ffi'):
|
if hasattr(backend, 'set_ffi'):
|
||||||
backend.set_ffi(self)
|
backend.set_ffi(self)
|
||||||
for name in backend.__dict__:
|
for name in backend.__dict__:
|
||||||
|
@ -77,6 +80,7 @@ class FFI(object):
|
||||||
#
|
#
|
||||||
with self._lock:
|
with self._lock:
|
||||||
self.BVoidP = self._get_cached_btype(model.voidp_type)
|
self.BVoidP = self._get_cached_btype(model.voidp_type)
|
||||||
|
self.BCharA = self._get_cached_btype(model.char_array_type)
|
||||||
if isinstance(backend, types.ModuleType):
|
if isinstance(backend, types.ModuleType):
|
||||||
# _cffi_backend: attach these constants to the class
|
# _cffi_backend: attach these constants to the class
|
||||||
if not hasattr(FFI, 'NULL'):
|
if not hasattr(FFI, 'NULL'):
|
||||||
|
@ -105,6 +109,11 @@ class FFI(object):
|
||||||
if override:
|
if override:
|
||||||
for cache in self._function_caches:
|
for cache in self._function_caches:
|
||||||
cache.clear()
|
cache.clear()
|
||||||
|
finishlist = self._parser._recomplete
|
||||||
|
if finishlist:
|
||||||
|
self._parser._recomplete = []
|
||||||
|
for tp in finishlist:
|
||||||
|
tp.finish_backend_type(self, finishlist)
|
||||||
|
|
||||||
def dlopen(self, name, flags=0):
|
def dlopen(self, name, flags=0):
|
||||||
"""Load and return a dynamic library identified by 'name'.
|
"""Load and return a dynamic library identified by 'name'.
|
||||||
|
@ -189,13 +198,16 @@ class FFI(object):
|
||||||
cdecl = self._typeof(cdecl)
|
cdecl = self._typeof(cdecl)
|
||||||
return self._backend.alignof(cdecl)
|
return self._backend.alignof(cdecl)
|
||||||
|
|
||||||
def offsetof(self, cdecl, fieldname):
|
def offsetof(self, cdecl, *fields_or_indexes):
|
||||||
"""Return the offset of the named field inside the given
|
"""Return the offset of the named field inside the given
|
||||||
structure, which must be given as a C type name.
|
structure or array, which must be given as a C type name.
|
||||||
|
You can give several field names in case of nested structures.
|
||||||
|
You can also give numeric values which correspond to array
|
||||||
|
items, in case of an array type.
|
||||||
"""
|
"""
|
||||||
if isinstance(cdecl, basestring):
|
if isinstance(cdecl, basestring):
|
||||||
cdecl = self._typeof(cdecl)
|
cdecl = self._typeof(cdecl)
|
||||||
return self._backend.typeoffsetof(cdecl, fieldname)[1]
|
return self._typeoffsetof(cdecl, *fields_or_indexes)[1]
|
||||||
|
|
||||||
def new(self, cdecl, init=None):
|
def new(self, cdecl, init=None):
|
||||||
"""Allocate an instance according to the specified C type and
|
"""Allocate an instance according to the specified C type and
|
||||||
|
@ -224,6 +236,30 @@ class FFI(object):
|
||||||
cdecl = self._typeof(cdecl)
|
cdecl = self._typeof(cdecl)
|
||||||
return self._backend.newp(cdecl, init)
|
return self._backend.newp(cdecl, init)
|
||||||
|
|
||||||
|
def new_allocator(self, alloc=None, free=None,
|
||||||
|
should_clear_after_alloc=True):
|
||||||
|
"""Return a new allocator, i.e. a function that behaves like ffi.new()
|
||||||
|
but uses the provided low-level 'alloc' and 'free' functions.
|
||||||
|
|
||||||
|
'alloc' is called with the size as argument. If it returns NULL, a
|
||||||
|
MemoryError is raised. 'free' is called with the result of 'alloc'
|
||||||
|
as argument. Both can be either Python function or directly C
|
||||||
|
functions. If 'free' is None, then no free function is called.
|
||||||
|
If both 'alloc' and 'free' are None, the default is used.
|
||||||
|
|
||||||
|
If 'should_clear_after_alloc' is set to False, then the memory
|
||||||
|
returned by 'alloc' is assumed to be already cleared (or you are
|
||||||
|
fine with garbage); otherwise CFFI will clear it.
|
||||||
|
"""
|
||||||
|
compiled_ffi = self._backend.FFI()
|
||||||
|
allocator = compiled_ffi.new_allocator(alloc, free,
|
||||||
|
should_clear_after_alloc)
|
||||||
|
def allocate(cdecl, init=None):
|
||||||
|
if isinstance(cdecl, basestring):
|
||||||
|
cdecl = self._typeof(cdecl)
|
||||||
|
return allocator(cdecl, init)
|
||||||
|
return allocate
|
||||||
|
|
||||||
def cast(self, cdecl, source):
|
def cast(self, cdecl, source):
|
||||||
"""Similar to a C cast: returns an instance of the named C
|
"""Similar to a C cast: returns an instance of the named C
|
||||||
type initialized with the given 'source'. The source is
|
type initialized with the given 'source'. The source is
|
||||||
|
@ -264,7 +300,33 @@ class FFI(object):
|
||||||
"""
|
"""
|
||||||
return self._backend.buffer(cdata, size)
|
return self._backend.buffer(cdata, size)
|
||||||
|
|
||||||
def callback(self, cdecl, python_callable=None, error=None):
|
def from_buffer(self, python_buffer):
|
||||||
|
"""Return a <cdata 'char[]'> that points to the data of the
|
||||||
|
given Python object, which must support the buffer interface.
|
||||||
|
Note that this is not meant to be used on the built-in types str,
|
||||||
|
unicode, or bytearray (you can build 'char[]' arrays explicitly)
|
||||||
|
but only on objects containing large quantities of raw data
|
||||||
|
in some other format, like 'array.array' or numpy arrays.
|
||||||
|
"""
|
||||||
|
return self._backend.from_buffer(self.BCharA, python_buffer)
|
||||||
|
|
||||||
|
def memmove(self, dest, src, n):
|
||||||
|
"""ffi.memmove(dest, src, n) copies n bytes of memory from src to dest.
|
||||||
|
|
||||||
|
Like the C function memmove(), the memory areas may overlap;
|
||||||
|
apart from that it behaves like the C function memcpy().
|
||||||
|
|
||||||
|
'src' can be any cdata ptr or array, or any Python buffer object.
|
||||||
|
'dest' can be any cdata ptr or array, or a writable Python buffer
|
||||||
|
object. The size to copy, 'n', is always measured in bytes.
|
||||||
|
|
||||||
|
Unlike other methods, this one supports all Python buffer including
|
||||||
|
byte strings and bytearrays---but it still does not support
|
||||||
|
non-contiguous buffers.
|
||||||
|
"""
|
||||||
|
return self._backend.memmove(dest, src, n)
|
||||||
|
|
||||||
|
def callback(self, cdecl, python_callable=None, error=None, onerror=None):
|
||||||
"""Return a callback object or a decorator making such a
|
"""Return a callback object or a decorator making such a
|
||||||
callback object. 'cdecl' must name a C function pointer type.
|
callback object. 'cdecl' must name a C function pointer type.
|
||||||
The callback invokes the specified 'python_callable' (which may
|
The callback invokes the specified 'python_callable' (which may
|
||||||
|
@ -276,7 +338,8 @@ class FFI(object):
|
||||||
if not callable(python_callable):
|
if not callable(python_callable):
|
||||||
raise TypeError("the 'python_callable' argument "
|
raise TypeError("the 'python_callable' argument "
|
||||||
"is not callable")
|
"is not callable")
|
||||||
return self._backend.callback(cdecl, python_callable, error)
|
return self._backend.callback(cdecl, python_callable,
|
||||||
|
error, onerror)
|
||||||
if isinstance(cdecl, basestring):
|
if isinstance(cdecl, basestring):
|
||||||
cdecl = self._typeof(cdecl, consider_function_as_funcptr=True)
|
cdecl = self._typeof(cdecl, consider_function_as_funcptr=True)
|
||||||
if python_callable is None:
|
if python_callable is None:
|
||||||
|
@ -305,6 +368,13 @@ class FFI(object):
|
||||||
data. Later, when this new cdata object is garbage-collected,
|
data. Later, when this new cdata object is garbage-collected,
|
||||||
'destructor(old_cdata_object)' will be called.
|
'destructor(old_cdata_object)' will be called.
|
||||||
"""
|
"""
|
||||||
|
try:
|
||||||
|
gcp = self._backend.gcp
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
return gcp(cdata, destructor)
|
||||||
|
#
|
||||||
with self._lock:
|
with self._lock:
|
||||||
try:
|
try:
|
||||||
gc_weakrefs = self.gc_weakrefs
|
gc_weakrefs = self.gc_weakrefs
|
||||||
|
@ -335,9 +405,23 @@ class FFI(object):
|
||||||
which requires binary compatibility in the signatures.
|
which requires binary compatibility in the signatures.
|
||||||
"""
|
"""
|
||||||
from .verifier import Verifier, _caller_dir_pycache
|
from .verifier import Verifier, _caller_dir_pycache
|
||||||
|
#
|
||||||
|
# If set_unicode(True) was called, insert the UNICODE and
|
||||||
|
# _UNICODE macro declarations
|
||||||
|
if self._windows_unicode:
|
||||||
|
self._apply_windows_unicode(kwargs)
|
||||||
|
#
|
||||||
|
# Set the tmpdir here, and not in Verifier.__init__: it picks
|
||||||
|
# up the caller's directory, which we want to be the caller of
|
||||||
|
# ffi.verify(), as opposed to the caller of Veritier().
|
||||||
tmpdir = tmpdir or _caller_dir_pycache()
|
tmpdir = tmpdir or _caller_dir_pycache()
|
||||||
|
#
|
||||||
|
# Make a Verifier() and use it to load the library.
|
||||||
self.verifier = Verifier(self, source, tmpdir, **kwargs)
|
self.verifier = Verifier(self, source, tmpdir, **kwargs)
|
||||||
lib = self.verifier.load_library()
|
lib = self.verifier.load_library()
|
||||||
|
#
|
||||||
|
# Save the loaded library for keep-alive purposes, even
|
||||||
|
# if the caller doesn't keep it alive itself (it should).
|
||||||
self._libraries.append(lib)
|
self._libraries.append(lib)
|
||||||
return lib
|
return lib
|
||||||
|
|
||||||
|
@ -356,15 +440,29 @@ class FFI(object):
|
||||||
with self._lock:
|
with self._lock:
|
||||||
return model.pointer_cache(self, ctype)
|
return model.pointer_cache(self, ctype)
|
||||||
|
|
||||||
def addressof(self, cdata, field=None):
|
def addressof(self, cdata, *fields_or_indexes):
|
||||||
"""Return the address of a <cdata 'struct-or-union'>.
|
"""Return the address of a <cdata 'struct-or-union'>.
|
||||||
If 'field' is specified, return the address of this field.
|
If 'fields_or_indexes' are given, returns the address of that
|
||||||
|
field or array item in the structure or array, recursively in
|
||||||
|
case of nested structures.
|
||||||
"""
|
"""
|
||||||
ctype = self._backend.typeof(cdata)
|
ctype = self._backend.typeof(cdata)
|
||||||
ctype, offset = self._backend.typeoffsetof(ctype, field)
|
if fields_or_indexes:
|
||||||
|
ctype, offset = self._typeoffsetof(ctype, *fields_or_indexes)
|
||||||
|
else:
|
||||||
|
if ctype.kind == "pointer":
|
||||||
|
raise TypeError("addressof(pointer)")
|
||||||
|
offset = 0
|
||||||
ctypeptr = self._pointer_to(ctype)
|
ctypeptr = self._pointer_to(ctype)
|
||||||
return self._backend.rawaddressof(ctypeptr, cdata, offset)
|
return self._backend.rawaddressof(ctypeptr, cdata, offset)
|
||||||
|
|
||||||
|
def _typeoffsetof(self, ctype, field_or_index, *fields_or_indexes):
|
||||||
|
ctype, offset = self._backend.typeoffsetof(ctype, field_or_index)
|
||||||
|
for field1 in fields_or_indexes:
|
||||||
|
ctype, offset1 = self._backend.typeoffsetof(ctype, field1, 1)
|
||||||
|
offset += offset1
|
||||||
|
return ctype, offset
|
||||||
|
|
||||||
def include(self, ffi_to_include):
|
def include(self, ffi_to_include):
|
||||||
"""Includes the typedefs, structs, unions and enums defined
|
"""Includes the typedefs, structs, unions and enums defined
|
||||||
in another FFI instance. Usage is similar to a #include in C,
|
in another FFI instance. Usage is similar to a #include in C,
|
||||||
|
@ -374,12 +472,19 @@ class FFI(object):
|
||||||
variables, which must anyway be accessed directly from the
|
variables, which must anyway be accessed directly from the
|
||||||
lib object returned by the original FFI instance.
|
lib object returned by the original FFI instance.
|
||||||
"""
|
"""
|
||||||
|
if not isinstance(ffi_to_include, FFI):
|
||||||
|
raise TypeError("ffi.include() expects an argument that is also of"
|
||||||
|
" type cffi.FFI, not %r" % (
|
||||||
|
type(ffi_to_include).__name__,))
|
||||||
|
if ffi_to_include is self:
|
||||||
|
raise ValueError("self.include(self)")
|
||||||
with ffi_to_include._lock:
|
with ffi_to_include._lock:
|
||||||
with self._lock:
|
with self._lock:
|
||||||
self._parser.include(ffi_to_include._parser)
|
self._parser.include(ffi_to_include._parser)
|
||||||
self._cdefsources.append('[')
|
self._cdefsources.append('[')
|
||||||
self._cdefsources.extend(ffi_to_include._cdefsources)
|
self._cdefsources.extend(ffi_to_include._cdefsources)
|
||||||
self._cdefsources.append(']')
|
self._cdefsources.append(']')
|
||||||
|
self._included_ffis.append(ffi_to_include)
|
||||||
|
|
||||||
def new_handle(self, x):
|
def new_handle(self, x):
|
||||||
return self._backend.newp_handle(self.BVoidP, x)
|
return self._backend.newp_handle(self.BVoidP, x)
|
||||||
|
@ -387,6 +492,112 @@ class FFI(object):
|
||||||
def from_handle(self, x):
|
def from_handle(self, x):
|
||||||
return self._backend.from_handle(x)
|
return self._backend.from_handle(x)
|
||||||
|
|
||||||
|
def set_unicode(self, enabled_flag):
|
||||||
|
"""Windows: if 'enabled_flag' is True, enable the UNICODE and
|
||||||
|
_UNICODE defines in C, and declare the types like TCHAR and LPTCSTR
|
||||||
|
to be (pointers to) wchar_t. If 'enabled_flag' is False,
|
||||||
|
declare these types to be (pointers to) plain 8-bit characters.
|
||||||
|
This is mostly for backward compatibility; you usually want True.
|
||||||
|
"""
|
||||||
|
if self._windows_unicode is not None:
|
||||||
|
raise ValueError("set_unicode() can only be called once")
|
||||||
|
enabled_flag = bool(enabled_flag)
|
||||||
|
if enabled_flag:
|
||||||
|
self.cdef("typedef wchar_t TBYTE;"
|
||||||
|
"typedef wchar_t TCHAR;"
|
||||||
|
"typedef const wchar_t *LPCTSTR;"
|
||||||
|
"typedef const wchar_t *PCTSTR;"
|
||||||
|
"typedef wchar_t *LPTSTR;"
|
||||||
|
"typedef wchar_t *PTSTR;"
|
||||||
|
"typedef TBYTE *PTBYTE;"
|
||||||
|
"typedef TCHAR *PTCHAR;")
|
||||||
|
else:
|
||||||
|
self.cdef("typedef char TBYTE;"
|
||||||
|
"typedef char TCHAR;"
|
||||||
|
"typedef const char *LPCTSTR;"
|
||||||
|
"typedef const char *PCTSTR;"
|
||||||
|
"typedef char *LPTSTR;"
|
||||||
|
"typedef char *PTSTR;"
|
||||||
|
"typedef TBYTE *PTBYTE;"
|
||||||
|
"typedef TCHAR *PTCHAR;")
|
||||||
|
self._windows_unicode = enabled_flag
|
||||||
|
|
||||||
|
def _apply_windows_unicode(self, kwds):
|
||||||
|
defmacros = kwds.get('define_macros', ())
|
||||||
|
if not isinstance(defmacros, (list, tuple)):
|
||||||
|
raise TypeError("'define_macros' must be a list or tuple")
|
||||||
|
defmacros = list(defmacros) + [('UNICODE', '1'),
|
||||||
|
('_UNICODE', '1')]
|
||||||
|
kwds['define_macros'] = defmacros
|
||||||
|
|
||||||
|
def set_source(self, module_name, source, source_extension='.c', **kwds):
|
||||||
|
if hasattr(self, '_assigned_source'):
|
||||||
|
raise ValueError("set_source() cannot be called several times "
|
||||||
|
"per ffi object")
|
||||||
|
if not isinstance(module_name, basestring):
|
||||||
|
raise TypeError("'module_name' must be a string")
|
||||||
|
self._assigned_source = (str(module_name), source,
|
||||||
|
source_extension, kwds)
|
||||||
|
|
||||||
|
def distutils_extension(self, tmpdir='build', verbose=True):
|
||||||
|
from distutils.dir_util import mkpath
|
||||||
|
from .recompiler import recompile
|
||||||
|
#
|
||||||
|
if not hasattr(self, '_assigned_source'):
|
||||||
|
if hasattr(self, 'verifier'): # fallback, 'tmpdir' ignored
|
||||||
|
return self.verifier.get_extension()
|
||||||
|
raise ValueError("set_source() must be called before"
|
||||||
|
" distutils_extension()")
|
||||||
|
module_name, source, source_extension, kwds = self._assigned_source
|
||||||
|
if source is None:
|
||||||
|
raise TypeError("distutils_extension() is only for C extension "
|
||||||
|
"modules, not for dlopen()-style pure Python "
|
||||||
|
"modules")
|
||||||
|
mkpath(tmpdir)
|
||||||
|
ext, updated = recompile(self, module_name,
|
||||||
|
source, tmpdir=tmpdir, extradir=tmpdir,
|
||||||
|
source_extension=source_extension,
|
||||||
|
call_c_compiler=False, **kwds)
|
||||||
|
if verbose:
|
||||||
|
if updated:
|
||||||
|
sys.stderr.write("regenerated: %r\n" % (ext.sources[0],))
|
||||||
|
else:
|
||||||
|
sys.stderr.write("not modified: %r\n" % (ext.sources[0],))
|
||||||
|
return ext
|
||||||
|
|
||||||
|
def emit_c_code(self, filename):
|
||||||
|
from .recompiler import recompile
|
||||||
|
#
|
||||||
|
if not hasattr(self, '_assigned_source'):
|
||||||
|
raise ValueError("set_source() must be called before emit_c_code()")
|
||||||
|
module_name, source, source_extension, kwds = self._assigned_source
|
||||||
|
if source is None:
|
||||||
|
raise TypeError("emit_c_code() is only for C extension modules, "
|
||||||
|
"not for dlopen()-style pure Python modules")
|
||||||
|
recompile(self, module_name, source,
|
||||||
|
c_file=filename, call_c_compiler=False, **kwds)
|
||||||
|
|
||||||
|
def emit_python_code(self, filename):
|
||||||
|
from .recompiler import recompile
|
||||||
|
#
|
||||||
|
if not hasattr(self, '_assigned_source'):
|
||||||
|
raise ValueError("set_source() must be called before emit_c_code()")
|
||||||
|
module_name, source, source_extension, kwds = self._assigned_source
|
||||||
|
if source is not None:
|
||||||
|
raise TypeError("emit_python_code() is only for dlopen()-style "
|
||||||
|
"pure Python modules, not for C extension modules")
|
||||||
|
recompile(self, module_name, source,
|
||||||
|
c_file=filename, call_c_compiler=False, **kwds)
|
||||||
|
|
||||||
|
def compile(self, tmpdir='.'):
|
||||||
|
from .recompiler import recompile
|
||||||
|
#
|
||||||
|
if not hasattr(self, '_assigned_source'):
|
||||||
|
raise ValueError("set_source() must be called before compile()")
|
||||||
|
module_name, source, source_extension, kwds = self._assigned_source
|
||||||
|
return recompile(self, module_name, source, tmpdir=tmpdir,
|
||||||
|
source_extension=source_extension, **kwds)
|
||||||
|
|
||||||
|
|
||||||
def _load_backend_lib(backend, name, flags):
|
def _load_backend_lib(backend, name, flags):
|
||||||
if name is None:
|
if name is None:
|
||||||
|
@ -414,7 +625,7 @@ def _make_ffi_library(ffi, libname, flags):
|
||||||
def make_accessor_locked(name):
|
def make_accessor_locked(name):
|
||||||
key = 'function ' + name
|
key = 'function ' + name
|
||||||
if key in ffi._parser._declarations:
|
if key in ffi._parser._declarations:
|
||||||
tp = ffi._parser._declarations[key]
|
tp, _ = ffi._parser._declarations[key]
|
||||||
BType = ffi._get_cached_btype(tp)
|
BType = ffi._get_cached_btype(tp)
|
||||||
try:
|
try:
|
||||||
value = backendlib.load_function(BType, name)
|
value = backendlib.load_function(BType, name)
|
||||||
|
@ -425,7 +636,7 @@ def _make_ffi_library(ffi, libname, flags):
|
||||||
#
|
#
|
||||||
key = 'variable ' + name
|
key = 'variable ' + name
|
||||||
if key in ffi._parser._declarations:
|
if key in ffi._parser._declarations:
|
||||||
tp = ffi._parser._declarations[key]
|
tp, _ = ffi._parser._declarations[key]
|
||||||
BType = ffi._get_cached_btype(tp)
|
BType = ffi._get_cached_btype(tp)
|
||||||
read_variable = backendlib.read_variable
|
read_variable = backendlib.read_variable
|
||||||
write_variable = backendlib.write_variable
|
write_variable = backendlib.write_variable
|
||||||
|
@ -436,12 +647,23 @@ def _make_ffi_library(ffi, libname, flags):
|
||||||
#
|
#
|
||||||
if not copied_enums:
|
if not copied_enums:
|
||||||
from . import model
|
from . import model
|
||||||
for key, tp in ffi._parser._declarations.items():
|
error = None
|
||||||
|
for key, (tp, _) in ffi._parser._declarations.items():
|
||||||
if not isinstance(tp, model.EnumType):
|
if not isinstance(tp, model.EnumType):
|
||||||
continue
|
continue
|
||||||
|
try:
|
||||||
|
tp.check_not_partial()
|
||||||
|
except Exception as e:
|
||||||
|
error = e
|
||||||
|
continue
|
||||||
for enumname, enumval in zip(tp.enumerators, tp.enumvalues):
|
for enumname, enumval in zip(tp.enumerators, tp.enumvalues):
|
||||||
if enumname not in library.__dict__:
|
if enumname not in library.__dict__:
|
||||||
library.__dict__[enumname] = enumval
|
library.__dict__[enumname] = enumval
|
||||||
|
if error is not None:
|
||||||
|
if name in library.__dict__:
|
||||||
|
return # ignore error, about a different enum
|
||||||
|
raise error
|
||||||
|
|
||||||
for key, val in ffi._parser._int_constants.items():
|
for key, val in ffi._parser._int_constants.items():
|
||||||
if key not in library.__dict__:
|
if key not in library.__dict__:
|
||||||
library.__dict__[key] = val
|
library.__dict__[key] = val
|
||||||
|
@ -450,6 +672,11 @@ def _make_ffi_library(ffi, libname, flags):
|
||||||
if name in library.__dict__:
|
if name in library.__dict__:
|
||||||
return
|
return
|
||||||
#
|
#
|
||||||
|
key = 'constant ' + name
|
||||||
|
if key in ffi._parser._declarations:
|
||||||
|
raise NotImplementedError("fetching a non-integer constant "
|
||||||
|
"after dlopen()")
|
||||||
|
#
|
||||||
raise AttributeError(name)
|
raise AttributeError(name)
|
||||||
#
|
#
|
||||||
def make_accessor(name):
|
def make_accessor(name):
|
||||||
|
|
|
@ -2,11 +2,10 @@ import ctypes, ctypes.util, operator, sys
|
||||||
from . import model
|
from . import model
|
||||||
|
|
||||||
if sys.version_info < (3,):
|
if sys.version_info < (3,):
|
||||||
integer_types = (int, long)
|
|
||||||
bytechr = chr
|
bytechr = chr
|
||||||
else:
|
else:
|
||||||
unicode = str
|
unicode = str
|
||||||
integer_types = int
|
long = int
|
||||||
xrange = range
|
xrange = range
|
||||||
bytechr = lambda num: bytes([num])
|
bytechr = lambda num: bytes([num])
|
||||||
|
|
||||||
|
@ -169,6 +168,7 @@ class CTypesGenericArray(CTypesData):
|
||||||
class CTypesGenericPtr(CTypesData):
|
class CTypesGenericPtr(CTypesData):
|
||||||
__slots__ = ['_address', '_as_ctype_ptr']
|
__slots__ = ['_address', '_as_ctype_ptr']
|
||||||
_automatic_casts = False
|
_automatic_casts = False
|
||||||
|
kind = "pointer"
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _newp(cls, init):
|
def _newp(cls, init):
|
||||||
|
@ -180,7 +180,7 @@ class CTypesGenericPtr(CTypesData):
|
||||||
address = 0
|
address = 0
|
||||||
elif isinstance(source, CTypesData):
|
elif isinstance(source, CTypesData):
|
||||||
address = source._cast_to_integer()
|
address = source._cast_to_integer()
|
||||||
elif isinstance(source, integer_types):
|
elif isinstance(source, (int, long)):
|
||||||
address = source
|
address = source
|
||||||
else:
|
else:
|
||||||
raise TypeError("bad type for cast to %r: %r" %
|
raise TypeError("bad type for cast to %r: %r" %
|
||||||
|
@ -357,7 +357,7 @@ class CTypesBackend(object):
|
||||||
is_signed = (ctype(-1).value == -1)
|
is_signed = (ctype(-1).value == -1)
|
||||||
#
|
#
|
||||||
def _cast_source_to_int(source):
|
def _cast_source_to_int(source):
|
||||||
if isinstance(source, (integer_types, float)):
|
if isinstance(source, (int, long, float)):
|
||||||
source = int(source)
|
source = int(source)
|
||||||
elif isinstance(source, CTypesData):
|
elif isinstance(source, CTypesData):
|
||||||
source = source._cast_to_integer()
|
source = source._cast_to_integer()
|
||||||
|
@ -370,10 +370,12 @@ class CTypesBackend(object):
|
||||||
(CTypesPrimitive, type(source).__name__))
|
(CTypesPrimitive, type(source).__name__))
|
||||||
return source
|
return source
|
||||||
#
|
#
|
||||||
|
kind1 = kind
|
||||||
class CTypesPrimitive(CTypesGenericPrimitive):
|
class CTypesPrimitive(CTypesGenericPrimitive):
|
||||||
__slots__ = ['_value']
|
__slots__ = ['_value']
|
||||||
_ctype = ctype
|
_ctype = ctype
|
||||||
_reftypename = '%s &' % name
|
_reftypename = '%s &' % name
|
||||||
|
kind = kind1
|
||||||
|
|
||||||
def __init__(self, value):
|
def __init__(self, value):
|
||||||
self._value = value
|
self._value = value
|
||||||
|
@ -396,7 +398,7 @@ class CTypesBackend(object):
|
||||||
if kind == 'bool':
|
if kind == 'bool':
|
||||||
@classmethod
|
@classmethod
|
||||||
def _cast_from(cls, source):
|
def _cast_from(cls, source):
|
||||||
if not isinstance(source, (integer_types, float)):
|
if not isinstance(source, (int, long, float)):
|
||||||
source = _cast_source_to_int(source)
|
source = _cast_source_to_int(source)
|
||||||
return cls(bool(source))
|
return cls(bool(source))
|
||||||
def __int__(self):
|
def __int__(self):
|
||||||
|
@ -435,7 +437,7 @@ class CTypesBackend(object):
|
||||||
if kind == 'int' or kind == 'byte' or kind == 'bool':
|
if kind == 'int' or kind == 'byte' or kind == 'bool':
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _to_ctypes(x):
|
def _to_ctypes(x):
|
||||||
if not isinstance(x, integer_types):
|
if not isinstance(x, (int, long)):
|
||||||
if isinstance(x, CTypesData):
|
if isinstance(x, CTypesData):
|
||||||
x = int(x)
|
x = int(x)
|
||||||
else:
|
else:
|
||||||
|
@ -462,7 +464,7 @@ class CTypesBackend(object):
|
||||||
if kind == 'float':
|
if kind == 'float':
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _to_ctypes(x):
|
def _to_ctypes(x):
|
||||||
if not isinstance(x, (integer_types, float, CTypesData)):
|
if not isinstance(x, (int, long, float, CTypesData)):
|
||||||
raise TypeError("float expected, got %s" %
|
raise TypeError("float expected, got %s" %
|
||||||
type(x).__name__)
|
type(x).__name__)
|
||||||
return ctype(x).value
|
return ctype(x).value
|
||||||
|
@ -526,14 +528,14 @@ class CTypesBackend(object):
|
||||||
self._own = True
|
self._own = True
|
||||||
|
|
||||||
def __add__(self, other):
|
def __add__(self, other):
|
||||||
if isinstance(other, integer_types):
|
if isinstance(other, (int, long)):
|
||||||
return self._new_pointer_at(self._address +
|
return self._new_pointer_at(self._address +
|
||||||
other * self._bitem_size)
|
other * self._bitem_size)
|
||||||
else:
|
else:
|
||||||
return NotImplemented
|
return NotImplemented
|
||||||
|
|
||||||
def __sub__(self, other):
|
def __sub__(self, other):
|
||||||
if isinstance(other, integer_types):
|
if isinstance(other, (int, long)):
|
||||||
return self._new_pointer_at(self._address -
|
return self._new_pointer_at(self._address -
|
||||||
other * self._bitem_size)
|
other * self._bitem_size)
|
||||||
elif type(self) is type(other):
|
elif type(self) is type(other):
|
||||||
|
@ -608,7 +610,7 @@ class CTypesBackend(object):
|
||||||
|
|
||||||
def __init__(self, init):
|
def __init__(self, init):
|
||||||
if length is None:
|
if length is None:
|
||||||
if isinstance(init, integer_types):
|
if isinstance(init, (int, long)):
|
||||||
len1 = init
|
len1 = init
|
||||||
init = None
|
init = None
|
||||||
elif kind == 'char' and isinstance(init, bytes):
|
elif kind == 'char' and isinstance(init, bytes):
|
||||||
|
@ -683,7 +685,7 @@ class CTypesBackend(object):
|
||||||
return CTypesPtr._arg_to_ctypes(value)
|
return CTypesPtr._arg_to_ctypes(value)
|
||||||
|
|
||||||
def __add__(self, other):
|
def __add__(self, other):
|
||||||
if isinstance(other, integer_types):
|
if isinstance(other, (int, long)):
|
||||||
return CTypesPtr._new_pointer_at(
|
return CTypesPtr._new_pointer_at(
|
||||||
ctypes.addressof(self._blob) +
|
ctypes.addressof(self._blob) +
|
||||||
other * ctypes.sizeof(BItem._ctype))
|
other * ctypes.sizeof(BItem._ctype))
|
||||||
|
@ -703,12 +705,13 @@ class CTypesBackend(object):
|
||||||
class struct_or_union(base_ctypes_class):
|
class struct_or_union(base_ctypes_class):
|
||||||
pass
|
pass
|
||||||
struct_or_union.__name__ = '%s_%s' % (kind, name)
|
struct_or_union.__name__ = '%s_%s' % (kind, name)
|
||||||
|
kind1 = kind
|
||||||
#
|
#
|
||||||
class CTypesStructOrUnion(CTypesBaseStructOrUnion):
|
class CTypesStructOrUnion(CTypesBaseStructOrUnion):
|
||||||
__slots__ = ['_blob']
|
__slots__ = ['_blob']
|
||||||
_ctype = struct_or_union
|
_ctype = struct_or_union
|
||||||
_reftypename = '%s &' % (name,)
|
_reftypename = '%s &' % (name,)
|
||||||
_kind = kind
|
_kind = kind = kind1
|
||||||
#
|
#
|
||||||
CTypesStructOrUnion._fix_class()
|
CTypesStructOrUnion._fix_class()
|
||||||
return CTypesStructOrUnion
|
return CTypesStructOrUnion
|
||||||
|
@ -986,7 +989,8 @@ class CTypesBackend(object):
|
||||||
def cast(self, BType, source):
|
def cast(self, BType, source):
|
||||||
return BType._cast_from(source)
|
return BType._cast_from(source)
|
||||||
|
|
||||||
def callback(self, BType, source, error):
|
def callback(self, BType, source, error, onerror):
|
||||||
|
assert onerror is None # XXX not implemented
|
||||||
return BType(source, error)
|
return BType(source, error)
|
||||||
|
|
||||||
typeof = type
|
typeof = type
|
||||||
|
@ -994,27 +998,42 @@ class CTypesBackend(object):
|
||||||
def getcname(self, BType, replace_with):
|
def getcname(self, BType, replace_with):
|
||||||
return BType._get_c_name(replace_with)
|
return BType._get_c_name(replace_with)
|
||||||
|
|
||||||
def typeoffsetof(self, BType, fieldname):
|
def typeoffsetof(self, BType, fieldname, num=0):
|
||||||
if fieldname is not None and issubclass(BType, CTypesGenericPtr):
|
if isinstance(fieldname, str):
|
||||||
|
if num == 0 and issubclass(BType, CTypesGenericPtr):
|
||||||
BType = BType._BItem
|
BType = BType._BItem
|
||||||
if not issubclass(BType, CTypesBaseStructOrUnion):
|
if not issubclass(BType, CTypesBaseStructOrUnion):
|
||||||
raise TypeError("expected a struct or union ctype")
|
raise TypeError("expected a struct or union ctype")
|
||||||
if fieldname is None:
|
|
||||||
return (BType, 0)
|
|
||||||
else:
|
|
||||||
BField = BType._bfield_types[fieldname]
|
BField = BType._bfield_types[fieldname]
|
||||||
if BField is Ellipsis:
|
if BField is Ellipsis:
|
||||||
raise TypeError("not supported for bitfields")
|
raise TypeError("not supported for bitfields")
|
||||||
return (BField, BType._offsetof(fieldname))
|
return (BField, BType._offsetof(fieldname))
|
||||||
|
elif isinstance(fieldname, (int, long)):
|
||||||
|
if issubclass(BType, CTypesGenericArray):
|
||||||
|
BType = BType._CTPtr
|
||||||
|
if not issubclass(BType, CTypesGenericPtr):
|
||||||
|
raise TypeError("expected an array or ptr ctype")
|
||||||
|
BItem = BType._BItem
|
||||||
|
offset = BItem._get_size() * fieldname
|
||||||
|
if offset > sys.maxsize:
|
||||||
|
raise OverflowError
|
||||||
|
return (BItem, offset)
|
||||||
|
else:
|
||||||
|
raise TypeError(type(fieldname))
|
||||||
|
|
||||||
def rawaddressof(self, BTypePtr, cdata, offset):
|
def rawaddressof(self, BTypePtr, cdata, offset=None):
|
||||||
if isinstance(cdata, CTypesBaseStructOrUnion):
|
if isinstance(cdata, CTypesBaseStructOrUnion):
|
||||||
ptr = ctypes.pointer(type(cdata)._to_ctypes(cdata))
|
ptr = ctypes.pointer(type(cdata)._to_ctypes(cdata))
|
||||||
elif isinstance(cdata, CTypesGenericPtr):
|
elif isinstance(cdata, CTypesGenericPtr):
|
||||||
|
if offset is None or not issubclass(type(cdata)._BItem,
|
||||||
|
CTypesBaseStructOrUnion):
|
||||||
|
raise TypeError("unexpected cdata type")
|
||||||
|
ptr = type(cdata)._to_ctypes(cdata)
|
||||||
|
elif isinstance(cdata, CTypesGenericArray):
|
||||||
ptr = type(cdata)._to_ctypes(cdata)
|
ptr = type(cdata)._to_ctypes(cdata)
|
||||||
else:
|
else:
|
||||||
raise TypeError("expected a <cdata 'struct-or-union'>")
|
raise TypeError("expected a <cdata 'struct-or-union'>")
|
||||||
if offset != 0:
|
if offset:
|
||||||
ptr = ctypes.cast(
|
ptr = ctypes.cast(
|
||||||
ctypes.c_void_p(
|
ctypes.c_void_p(
|
||||||
ctypes.cast(ptr, ctypes.c_void_p).value + offset),
|
ctypes.cast(ptr, ctypes.c_void_p).value + offset),
|
||||||
|
|
176
Linux_x86_64/lib/python3.4/site-packages/cffi/cffi_opcode.py
Normal file
176
Linux_x86_64/lib/python3.4/site-packages/cffi/cffi_opcode.py
Normal file
|
@ -0,0 +1,176 @@
|
||||||
|
|
||||||
|
class CffiOp(object):
|
||||||
|
def __init__(self, op, arg):
|
||||||
|
self.op = op
|
||||||
|
self.arg = arg
|
||||||
|
|
||||||
|
def as_c_expr(self):
|
||||||
|
if self.op is None:
|
||||||
|
assert isinstance(self.arg, str)
|
||||||
|
return '(_cffi_opcode_t)(%s)' % (self.arg,)
|
||||||
|
classname = CLASS_NAME[self.op]
|
||||||
|
return '_CFFI_OP(_CFFI_OP_%s, %s)' % (classname, self.arg)
|
||||||
|
|
||||||
|
def as_python_bytes(self):
|
||||||
|
if self.op is None and self.arg.isdigit():
|
||||||
|
value = int(self.arg) # non-negative: '-' not in self.arg
|
||||||
|
if value >= 2**31:
|
||||||
|
raise OverflowError("cannot emit %r: limited to 2**31-1"
|
||||||
|
% (self.arg,))
|
||||||
|
return format_four_bytes(value)
|
||||||
|
if isinstance(self.arg, str):
|
||||||
|
from .ffiplatform import VerificationError
|
||||||
|
raise VerificationError("cannot emit to Python: %r" % (self.arg,))
|
||||||
|
return format_four_bytes((self.arg << 8) | self.op)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
classname = CLASS_NAME.get(self.op, self.op)
|
||||||
|
return '(%s %s)' % (classname, self.arg)
|
||||||
|
|
||||||
|
def format_four_bytes(num):
|
||||||
|
return '\\x%02X\\x%02X\\x%02X\\x%02X' % (
|
||||||
|
(num >> 24) & 0xFF,
|
||||||
|
(num >> 16) & 0xFF,
|
||||||
|
(num >> 8) & 0xFF,
|
||||||
|
(num ) & 0xFF)
|
||||||
|
|
||||||
|
OP_PRIMITIVE = 1
|
||||||
|
OP_POINTER = 3
|
||||||
|
OP_ARRAY = 5
|
||||||
|
OP_OPEN_ARRAY = 7
|
||||||
|
OP_STRUCT_UNION = 9
|
||||||
|
OP_ENUM = 11
|
||||||
|
OP_FUNCTION = 13
|
||||||
|
OP_FUNCTION_END = 15
|
||||||
|
OP_NOOP = 17
|
||||||
|
OP_BITFIELD = 19
|
||||||
|
OP_TYPENAME = 21
|
||||||
|
OP_CPYTHON_BLTN_V = 23 # varargs
|
||||||
|
OP_CPYTHON_BLTN_N = 25 # noargs
|
||||||
|
OP_CPYTHON_BLTN_O = 27 # O (i.e. a single arg)
|
||||||
|
OP_CONSTANT = 29
|
||||||
|
OP_CONSTANT_INT = 31
|
||||||
|
OP_GLOBAL_VAR = 33
|
||||||
|
OP_DLOPEN_FUNC = 35
|
||||||
|
OP_DLOPEN_CONST = 37
|
||||||
|
OP_GLOBAL_VAR_F = 39
|
||||||
|
|
||||||
|
PRIM_VOID = 0
|
||||||
|
PRIM_BOOL = 1
|
||||||
|
PRIM_CHAR = 2
|
||||||
|
PRIM_SCHAR = 3
|
||||||
|
PRIM_UCHAR = 4
|
||||||
|
PRIM_SHORT = 5
|
||||||
|
PRIM_USHORT = 6
|
||||||
|
PRIM_INT = 7
|
||||||
|
PRIM_UINT = 8
|
||||||
|
PRIM_LONG = 9
|
||||||
|
PRIM_ULONG = 10
|
||||||
|
PRIM_LONGLONG = 11
|
||||||
|
PRIM_ULONGLONG = 12
|
||||||
|
PRIM_FLOAT = 13
|
||||||
|
PRIM_DOUBLE = 14
|
||||||
|
PRIM_LONGDOUBLE = 15
|
||||||
|
|
||||||
|
PRIM_WCHAR = 16
|
||||||
|
PRIM_INT8 = 17
|
||||||
|
PRIM_UINT8 = 18
|
||||||
|
PRIM_INT16 = 19
|
||||||
|
PRIM_UINT16 = 20
|
||||||
|
PRIM_INT32 = 21
|
||||||
|
PRIM_UINT32 = 22
|
||||||
|
PRIM_INT64 = 23
|
||||||
|
PRIM_UINT64 = 24
|
||||||
|
PRIM_INTPTR = 25
|
||||||
|
PRIM_UINTPTR = 26
|
||||||
|
PRIM_PTRDIFF = 27
|
||||||
|
PRIM_SIZE = 28
|
||||||
|
PRIM_SSIZE = 29
|
||||||
|
PRIM_INT_LEAST8 = 30
|
||||||
|
PRIM_UINT_LEAST8 = 31
|
||||||
|
PRIM_INT_LEAST16 = 32
|
||||||
|
PRIM_UINT_LEAST16 = 33
|
||||||
|
PRIM_INT_LEAST32 = 34
|
||||||
|
PRIM_UINT_LEAST32 = 35
|
||||||
|
PRIM_INT_LEAST64 = 36
|
||||||
|
PRIM_UINT_LEAST64 = 37
|
||||||
|
PRIM_INT_FAST8 = 38
|
||||||
|
PRIM_UINT_FAST8 = 39
|
||||||
|
PRIM_INT_FAST16 = 40
|
||||||
|
PRIM_UINT_FAST16 = 41
|
||||||
|
PRIM_INT_FAST32 = 42
|
||||||
|
PRIM_UINT_FAST32 = 43
|
||||||
|
PRIM_INT_FAST64 = 44
|
||||||
|
PRIM_UINT_FAST64 = 45
|
||||||
|
PRIM_INTMAX = 46
|
||||||
|
PRIM_UINTMAX = 47
|
||||||
|
|
||||||
|
_NUM_PRIM = 48
|
||||||
|
_UNKNOWN_PRIM = -1
|
||||||
|
_UNKNOWN_FLOAT_PRIM = -2
|
||||||
|
_UNKNOWN_LONG_DOUBLE = -3
|
||||||
|
|
||||||
|
PRIMITIVE_TO_INDEX = {
|
||||||
|
'char': PRIM_CHAR,
|
||||||
|
'short': PRIM_SHORT,
|
||||||
|
'int': PRIM_INT,
|
||||||
|
'long': PRIM_LONG,
|
||||||
|
'long long': PRIM_LONGLONG,
|
||||||
|
'signed char': PRIM_SCHAR,
|
||||||
|
'unsigned char': PRIM_UCHAR,
|
||||||
|
'unsigned short': PRIM_USHORT,
|
||||||
|
'unsigned int': PRIM_UINT,
|
||||||
|
'unsigned long': PRIM_ULONG,
|
||||||
|
'unsigned long long': PRIM_ULONGLONG,
|
||||||
|
'float': PRIM_FLOAT,
|
||||||
|
'double': PRIM_DOUBLE,
|
||||||
|
'long double': PRIM_LONGDOUBLE,
|
||||||
|
'_Bool': PRIM_BOOL,
|
||||||
|
'wchar_t': PRIM_WCHAR,
|
||||||
|
'int8_t': PRIM_INT8,
|
||||||
|
'uint8_t': PRIM_UINT8,
|
||||||
|
'int16_t': PRIM_INT16,
|
||||||
|
'uint16_t': PRIM_UINT16,
|
||||||
|
'int32_t': PRIM_INT32,
|
||||||
|
'uint32_t': PRIM_UINT32,
|
||||||
|
'int64_t': PRIM_INT64,
|
||||||
|
'uint64_t': PRIM_UINT64,
|
||||||
|
'intptr_t': PRIM_INTPTR,
|
||||||
|
'uintptr_t': PRIM_UINTPTR,
|
||||||
|
'ptrdiff_t': PRIM_PTRDIFF,
|
||||||
|
'size_t': PRIM_SIZE,
|
||||||
|
'ssize_t': PRIM_SSIZE,
|
||||||
|
'int_least8_t': PRIM_INT_LEAST8,
|
||||||
|
'uint_least8_t': PRIM_UINT_LEAST8,
|
||||||
|
'int_least16_t': PRIM_INT_LEAST16,
|
||||||
|
'uint_least16_t': PRIM_UINT_LEAST16,
|
||||||
|
'int_least32_t': PRIM_INT_LEAST32,
|
||||||
|
'uint_least32_t': PRIM_UINT_LEAST32,
|
||||||
|
'int_least64_t': PRIM_INT_LEAST64,
|
||||||
|
'uint_least64_t': PRIM_UINT_LEAST64,
|
||||||
|
'int_fast8_t': PRIM_INT_FAST8,
|
||||||
|
'uint_fast8_t': PRIM_UINT_FAST8,
|
||||||
|
'int_fast16_t': PRIM_INT_FAST16,
|
||||||
|
'uint_fast16_t': PRIM_UINT_FAST16,
|
||||||
|
'int_fast32_t': PRIM_INT_FAST32,
|
||||||
|
'uint_fast32_t': PRIM_UINT_FAST32,
|
||||||
|
'int_fast64_t': PRIM_INT_FAST64,
|
||||||
|
'uint_fast64_t': PRIM_UINT_FAST64,
|
||||||
|
'intmax_t': PRIM_INTMAX,
|
||||||
|
'uintmax_t': PRIM_UINTMAX,
|
||||||
|
}
|
||||||
|
|
||||||
|
F_UNION = 0x01
|
||||||
|
F_CHECK_FIELDS = 0x02
|
||||||
|
F_PACKED = 0x04
|
||||||
|
F_EXTERNAL = 0x08
|
||||||
|
F_OPAQUE = 0x10
|
||||||
|
|
||||||
|
G_FLAGS = dict([('_CFFI_' + _key, globals()[_key])
|
||||||
|
for _key in ['F_UNION', 'F_CHECK_FIELDS', 'F_PACKED',
|
||||||
|
'F_EXTERNAL', 'F_OPAQUE']])
|
||||||
|
|
||||||
|
CLASS_NAME = {}
|
||||||
|
for _name, _value in list(globals().items()):
|
||||||
|
if _name.startswith('OP_') and isinstance(_value, int):
|
||||||
|
CLASS_NAME[_value] = _name[3:]
|
|
@ -29,6 +29,9 @@ def resolve_common_type(commontype):
|
||||||
result = model.PointerType(resolve_common_type(result[:-2]))
|
result = model.PointerType(resolve_common_type(result[:-2]))
|
||||||
elif result in model.PrimitiveType.ALL_PRIMITIVE_TYPES:
|
elif result in model.PrimitiveType.ALL_PRIMITIVE_TYPES:
|
||||||
result = model.PrimitiveType(result)
|
result = model.PrimitiveType(result)
|
||||||
|
elif result == 'set-unicode-needed':
|
||||||
|
raise api.FFIError("The Windows type %r is only available after "
|
||||||
|
"you call ffi.set_unicode()" % (commontype,))
|
||||||
else:
|
else:
|
||||||
if commontype == result:
|
if commontype == result:
|
||||||
raise api.FFIError("Unsupported type: %r. Please file a bug "
|
raise api.FFIError("Unsupported type: %r. Please file a bug "
|
||||||
|
@ -86,8 +89,6 @@ def win_common_types(maxsize):
|
||||||
"ULONGLONG": "unsigned long long",
|
"ULONGLONG": "unsigned long long",
|
||||||
"WCHAR": "wchar_t",
|
"WCHAR": "wchar_t",
|
||||||
"SHORT": "short",
|
"SHORT": "short",
|
||||||
"TBYTE": "WCHAR",
|
|
||||||
"TCHAR": "WCHAR",
|
|
||||||
"UCHAR": "unsigned char",
|
"UCHAR": "unsigned char",
|
||||||
"UINT": "unsigned int",
|
"UINT": "unsigned int",
|
||||||
"UINT8": "unsigned char",
|
"UINT8": "unsigned char",
|
||||||
|
@ -157,14 +158,12 @@ def win_common_types(maxsize):
|
||||||
|
|
||||||
"LPCVOID": model.const_voidp_type,
|
"LPCVOID": model.const_voidp_type,
|
||||||
"LPCWSTR": "const WCHAR *",
|
"LPCWSTR": "const WCHAR *",
|
||||||
"LPCTSTR": "LPCWSTR",
|
|
||||||
"LPDWORD": "DWORD *",
|
"LPDWORD": "DWORD *",
|
||||||
"LPHANDLE": "HANDLE *",
|
"LPHANDLE": "HANDLE *",
|
||||||
"LPINT": "int *",
|
"LPINT": "int *",
|
||||||
"LPLONG": "long *",
|
"LPLONG": "long *",
|
||||||
"LPSTR": "CHAR *",
|
"LPSTR": "CHAR *",
|
||||||
"LPWSTR": "WCHAR *",
|
"LPWSTR": "WCHAR *",
|
||||||
"LPTSTR": "LPWSTR",
|
|
||||||
"LPVOID": model.voidp_type,
|
"LPVOID": model.voidp_type,
|
||||||
"LPWORD": "WORD *",
|
"LPWORD": "WORD *",
|
||||||
"LRESULT": "LONG_PTR",
|
"LRESULT": "LONG_PTR",
|
||||||
|
@ -173,7 +172,6 @@ def win_common_types(maxsize):
|
||||||
"PBYTE": "BYTE *",
|
"PBYTE": "BYTE *",
|
||||||
"PCHAR": "CHAR *",
|
"PCHAR": "CHAR *",
|
||||||
"PCSTR": "const CHAR *",
|
"PCSTR": "const CHAR *",
|
||||||
"PCTSTR": "LPCWSTR",
|
|
||||||
"PCWSTR": "const WCHAR *",
|
"PCWSTR": "const WCHAR *",
|
||||||
"PDWORD": "DWORD *",
|
"PDWORD": "DWORD *",
|
||||||
"PDWORDLONG": "DWORDLONG *",
|
"PDWORDLONG": "DWORDLONG *",
|
||||||
|
@ -200,9 +198,6 @@ def win_common_types(maxsize):
|
||||||
"PSIZE_T": "SIZE_T *",
|
"PSIZE_T": "SIZE_T *",
|
||||||
"PSSIZE_T": "SSIZE_T *",
|
"PSSIZE_T": "SSIZE_T *",
|
||||||
"PSTR": "CHAR *",
|
"PSTR": "CHAR *",
|
||||||
"PTBYTE": "TBYTE *",
|
|
||||||
"PTCHAR": "TCHAR *",
|
|
||||||
"PTSTR": "LPWSTR",
|
|
||||||
"PUCHAR": "UCHAR *",
|
"PUCHAR": "UCHAR *",
|
||||||
"PUHALF_PTR": "UHALF_PTR *",
|
"PUHALF_PTR": "UHALF_PTR *",
|
||||||
"PUINT": "UINT *",
|
"PUINT": "UINT *",
|
||||||
|
@ -240,6 +235,15 @@ def win_common_types(maxsize):
|
||||||
"USN": "LONGLONG",
|
"USN": "LONGLONG",
|
||||||
"VOID": model.void_type,
|
"VOID": model.void_type,
|
||||||
"WPARAM": "UINT_PTR",
|
"WPARAM": "UINT_PTR",
|
||||||
|
|
||||||
|
"TBYTE": "set-unicode-needed",
|
||||||
|
"TCHAR": "set-unicode-needed",
|
||||||
|
"LPCTSTR": "set-unicode-needed",
|
||||||
|
"PCTSTR": "set-unicode-needed",
|
||||||
|
"LPTSTR": "set-unicode-needed",
|
||||||
|
"PTSTR": "set-unicode-needed",
|
||||||
|
"PTBYTE": "set-unicode-needed",
|
||||||
|
"PTCHAR": "set-unicode-needed",
|
||||||
})
|
})
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
from . import api, model
|
from . import api, model
|
||||||
from .commontypes import COMMON_TYPES, resolve_common_type
|
from .commontypes import COMMON_TYPES, resolve_common_type
|
||||||
try:
|
try:
|
||||||
|
@ -16,15 +15,20 @@ try:
|
||||||
except ImportError:
|
except ImportError:
|
||||||
lock = None
|
lock = None
|
||||||
|
|
||||||
_r_comment = re.compile(r"/\*.*?\*/|//.*?$", re.DOTALL | re.MULTILINE)
|
_r_comment = re.compile(r"/\*.*?\*/|//([^\n\\]|\\.)*?$",
|
||||||
_r_define = re.compile(r"^\s*#\s*define\s+([A-Za-z_][A-Za-z_0-9]*)\s+(.*?)$",
|
re.DOTALL | re.MULTILINE)
|
||||||
re.MULTILINE)
|
_r_define = re.compile(r"^\s*#\s*define\s+([A-Za-z_][A-Za-z_0-9]*)"
|
||||||
|
r"\b((?:[^\n\\]|\\.)*?)$",
|
||||||
|
re.DOTALL | re.MULTILINE)
|
||||||
_r_partial_enum = re.compile(r"=\s*\.\.\.\s*[,}]|\.\.\.\s*\}")
|
_r_partial_enum = re.compile(r"=\s*\.\.\.\s*[,}]|\.\.\.\s*\}")
|
||||||
_r_enum_dotdotdot = re.compile(r"__dotdotdot\d+__$")
|
_r_enum_dotdotdot = re.compile(r"__dotdotdot\d+__$")
|
||||||
_r_partial_array = re.compile(r"\[\s*\.\.\.\s*\]")
|
_r_partial_array = re.compile(r"\[\s*\.\.\.\s*\]")
|
||||||
_r_words = re.compile(r"\w+|\S")
|
_r_words = re.compile(r"\w+|\S")
|
||||||
_parser_cache = None
|
_parser_cache = None
|
||||||
_r_int_literal = re.compile(r"^0?x?[0-9a-f]+u?l?$", re.IGNORECASE)
|
_r_int_literal = re.compile(r"-?0?x?[0-9a-f]+[lu]*$", re.IGNORECASE)
|
||||||
|
_r_stdcall1 = re.compile(r"\b(__stdcall|WINAPI)\b")
|
||||||
|
_r_stdcall2 = re.compile(r"[(]\s*(__stdcall|WINAPI)\b")
|
||||||
|
_r_cdecl = re.compile(r"\b__cdecl\b")
|
||||||
|
|
||||||
def _get_parser():
|
def _get_parser():
|
||||||
global _parser_cache
|
global _parser_cache
|
||||||
|
@ -40,8 +44,17 @@ def _preprocess(csource):
|
||||||
macros = {}
|
macros = {}
|
||||||
for match in _r_define.finditer(csource):
|
for match in _r_define.finditer(csource):
|
||||||
macroname, macrovalue = match.groups()
|
macroname, macrovalue = match.groups()
|
||||||
|
macrovalue = macrovalue.replace('\\\n', '').strip()
|
||||||
macros[macroname] = macrovalue
|
macros[macroname] = macrovalue
|
||||||
csource = _r_define.sub('', csource)
|
csource = _r_define.sub('', csource)
|
||||||
|
# BIG HACK: replace WINAPI or __stdcall with "volatile const".
|
||||||
|
# It doesn't make sense for the return type of a function to be
|
||||||
|
# "volatile volatile const", so we abuse it to detect __stdcall...
|
||||||
|
# Hack number 2 is that "int(volatile *fptr)();" is not valid C
|
||||||
|
# syntax, so we place the "volatile" before the opening parenthesis.
|
||||||
|
csource = _r_stdcall2.sub(' volatile volatile const(', csource)
|
||||||
|
csource = _r_stdcall1.sub(' volatile volatile const ', csource)
|
||||||
|
csource = _r_cdecl.sub(' ', csource)
|
||||||
# Replace "[...]" with "[__dotdotdotarray__]"
|
# Replace "[...]" with "[__dotdotdotarray__]"
|
||||||
csource = _r_partial_array.sub('[__dotdotdotarray__]', csource)
|
csource = _r_partial_array.sub('[__dotdotdotarray__]', csource)
|
||||||
# Replace "...}" with "__dotdotdotNUM__}". This construction should
|
# Replace "...}" with "__dotdotdotNUM__}". This construction should
|
||||||
|
@ -73,9 +86,13 @@ def _common_type_names(csource):
|
||||||
# but should be fine for all the common types.
|
# but should be fine for all the common types.
|
||||||
look_for_words = set(COMMON_TYPES)
|
look_for_words = set(COMMON_TYPES)
|
||||||
look_for_words.add(';')
|
look_for_words.add(';')
|
||||||
|
look_for_words.add(',')
|
||||||
|
look_for_words.add('(')
|
||||||
|
look_for_words.add(')')
|
||||||
look_for_words.add('typedef')
|
look_for_words.add('typedef')
|
||||||
words_used = set()
|
words_used = set()
|
||||||
is_typedef = False
|
is_typedef = False
|
||||||
|
paren = 0
|
||||||
previous_word = ''
|
previous_word = ''
|
||||||
for word in _r_words.findall(csource):
|
for word in _r_words.findall(csource):
|
||||||
if word in look_for_words:
|
if word in look_for_words:
|
||||||
|
@ -86,6 +103,15 @@ def _common_type_names(csource):
|
||||||
is_typedef = False
|
is_typedef = False
|
||||||
elif word == 'typedef':
|
elif word == 'typedef':
|
||||||
is_typedef = True
|
is_typedef = True
|
||||||
|
paren = 0
|
||||||
|
elif word == '(':
|
||||||
|
paren += 1
|
||||||
|
elif word == ')':
|
||||||
|
paren -= 1
|
||||||
|
elif word == ',':
|
||||||
|
if is_typedef and paren == 0:
|
||||||
|
words_used.discard(previous_word)
|
||||||
|
look_for_words.discard(previous_word)
|
||||||
else: # word in COMMON_TYPES
|
else: # word in COMMON_TYPES
|
||||||
words_used.add(word)
|
words_used.add(word)
|
||||||
previous_word = word
|
previous_word = word
|
||||||
|
@ -96,11 +122,14 @@ class Parser(object):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._declarations = {}
|
self._declarations = {}
|
||||||
|
self._included_declarations = set()
|
||||||
self._anonymous_counter = 0
|
self._anonymous_counter = 0
|
||||||
self._structnode2type = weakref.WeakKeyDictionary()
|
self._structnode2type = weakref.WeakKeyDictionary()
|
||||||
self._override = False
|
self._override = False
|
||||||
self._packed = False
|
self._packed = False
|
||||||
self._int_constants = {}
|
self._int_constants = {}
|
||||||
|
self._recomplete = []
|
||||||
|
self._uses_new_feature = None
|
||||||
|
|
||||||
def _parse(self, csource):
|
def _parse(self, csource):
|
||||||
csource, macros = _preprocess(csource)
|
csource, macros = _preprocess(csource)
|
||||||
|
@ -187,9 +216,10 @@ class Parser(object):
|
||||||
if not decl.name:
|
if not decl.name:
|
||||||
raise api.CDefError("typedef does not declare any name",
|
raise api.CDefError("typedef does not declare any name",
|
||||||
decl)
|
decl)
|
||||||
|
quals = 0
|
||||||
if (isinstance(decl.type.type, pycparser.c_ast.IdentifierType)
|
if (isinstance(decl.type.type, pycparser.c_ast.IdentifierType)
|
||||||
and decl.type.type.names == ['__dotdotdot__']):
|
and decl.type.type.names[-1] == '__dotdotdot__'):
|
||||||
realtype = model.unknown_type(decl.name)
|
realtype = self._get_unknown_type(decl)
|
||||||
elif (isinstance(decl.type, pycparser.c_ast.PtrDecl) and
|
elif (isinstance(decl.type, pycparser.c_ast.PtrDecl) and
|
||||||
isinstance(decl.type.type, pycparser.c_ast.TypeDecl) and
|
isinstance(decl.type.type, pycparser.c_ast.TypeDecl) and
|
||||||
isinstance(decl.type.type.type,
|
isinstance(decl.type.type.type,
|
||||||
|
@ -197,8 +227,9 @@ class Parser(object):
|
||||||
decl.type.type.type.names == ['__dotdotdot__']):
|
decl.type.type.type.names == ['__dotdotdot__']):
|
||||||
realtype = model.unknown_ptr_type(decl.name)
|
realtype = model.unknown_ptr_type(decl.name)
|
||||||
else:
|
else:
|
||||||
realtype = self._get_type(decl.type, name=decl.name)
|
realtype, quals = self._get_type_and_quals(
|
||||||
self._declare('typedef ' + decl.name, realtype)
|
decl.type, name=decl.name)
|
||||||
|
self._declare('typedef ' + decl.name, realtype, quals=quals)
|
||||||
else:
|
else:
|
||||||
raise api.CDefError("unrecognized construct", decl)
|
raise api.CDefError("unrecognized construct", decl)
|
||||||
except api.FFIError as e:
|
except api.FFIError as e:
|
||||||
|
@ -209,60 +240,84 @@ class Parser(object):
|
||||||
|
|
||||||
def _add_constants(self, key, val):
|
def _add_constants(self, key, val):
|
||||||
if key in self._int_constants:
|
if key in self._int_constants:
|
||||||
|
if self._int_constants[key] == val:
|
||||||
|
return # ignore identical double declarations
|
||||||
raise api.FFIError(
|
raise api.FFIError(
|
||||||
"multiple declarations of constant: %s" % (key,))
|
"multiple declarations of constant: %s" % (key,))
|
||||||
self._int_constants[key] = val
|
self._int_constants[key] = val
|
||||||
|
|
||||||
|
def _add_integer_constant(self, name, int_str):
|
||||||
|
int_str = int_str.lower().rstrip("ul")
|
||||||
|
neg = int_str.startswith('-')
|
||||||
|
if neg:
|
||||||
|
int_str = int_str[1:]
|
||||||
|
# "010" is not valid oct in py3
|
||||||
|
if (int_str.startswith("0") and int_str != '0'
|
||||||
|
and not int_str.startswith("0x")):
|
||||||
|
int_str = "0o" + int_str[1:]
|
||||||
|
pyvalue = int(int_str, 0)
|
||||||
|
if neg:
|
||||||
|
pyvalue = -pyvalue
|
||||||
|
self._add_constants(name, pyvalue)
|
||||||
|
self._declare('macro ' + name, pyvalue)
|
||||||
|
|
||||||
def _process_macros(self, macros):
|
def _process_macros(self, macros):
|
||||||
for key, value in macros.items():
|
for key, value in macros.items():
|
||||||
value = value.strip()
|
value = value.strip()
|
||||||
match = _r_int_literal.search(value)
|
if _r_int_literal.match(value):
|
||||||
if match is not None:
|
self._add_integer_constant(key, value)
|
||||||
int_str = match.group(0).lower().rstrip("ul")
|
|
||||||
|
|
||||||
# "010" is not valid oct in py3
|
|
||||||
if (int_str.startswith("0") and
|
|
||||||
int_str != "0" and
|
|
||||||
not int_str.startswith("0x")):
|
|
||||||
int_str = "0o" + int_str[1:]
|
|
||||||
|
|
||||||
pyvalue = int(int_str, 0)
|
|
||||||
self._add_constants(key, pyvalue)
|
|
||||||
elif value == '...':
|
elif value == '...':
|
||||||
self._declare('macro ' + key, value)
|
self._declare('macro ' + key, value)
|
||||||
else:
|
else:
|
||||||
raise api.CDefError('only supports the syntax "#define '
|
raise api.CDefError(
|
||||||
'%s ..." (literally) or "#define '
|
'only supports one of the following syntax:\n'
|
||||||
'%s 0x1FF" for now' % (key, key))
|
' #define %s ... (literally dot-dot-dot)\n'
|
||||||
|
' #define %s NUMBER (with NUMBER an integer'
|
||||||
|
' constant, decimal/hex/octal)\n'
|
||||||
|
'got:\n'
|
||||||
|
' #define %s %s'
|
||||||
|
% (key, key, key, value))
|
||||||
|
|
||||||
def _parse_decl(self, decl):
|
def _parse_decl(self, decl):
|
||||||
node = decl.type
|
node = decl.type
|
||||||
if isinstance(node, pycparser.c_ast.FuncDecl):
|
if isinstance(node, pycparser.c_ast.FuncDecl):
|
||||||
tp = self._get_type(node, name=decl.name)
|
tp, quals = self._get_type_and_quals(node, name=decl.name)
|
||||||
assert isinstance(tp, model.RawFunctionType)
|
assert isinstance(tp, model.RawFunctionType)
|
||||||
tp = self._get_type_pointer(tp)
|
tp = self._get_type_pointer(tp, quals)
|
||||||
self._declare('function ' + decl.name, tp)
|
self._declare('function ' + decl.name, tp)
|
||||||
else:
|
else:
|
||||||
if isinstance(node, pycparser.c_ast.Struct):
|
if isinstance(node, pycparser.c_ast.Struct):
|
||||||
# XXX do we need self._declare in any of those?
|
|
||||||
if node.decls is not None:
|
|
||||||
self._get_struct_union_enum_type('struct', node)
|
self._get_struct_union_enum_type('struct', node)
|
||||||
elif isinstance(node, pycparser.c_ast.Union):
|
elif isinstance(node, pycparser.c_ast.Union):
|
||||||
if node.decls is not None:
|
|
||||||
self._get_struct_union_enum_type('union', node)
|
self._get_struct_union_enum_type('union', node)
|
||||||
elif isinstance(node, pycparser.c_ast.Enum):
|
elif isinstance(node, pycparser.c_ast.Enum):
|
||||||
if node.values is not None:
|
|
||||||
self._get_struct_union_enum_type('enum', node)
|
self._get_struct_union_enum_type('enum', node)
|
||||||
elif not decl.name:
|
elif not decl.name:
|
||||||
raise api.CDefError("construct does not declare any variable",
|
raise api.CDefError("construct does not declare any variable",
|
||||||
decl)
|
decl)
|
||||||
#
|
#
|
||||||
if decl.name:
|
if decl.name:
|
||||||
tp = self._get_type(node, partial_length_ok=True)
|
tp, quals = self._get_type_and_quals(node,
|
||||||
if self._is_constant_globalvar(node):
|
partial_length_ok=True)
|
||||||
self._declare('constant ' + decl.name, tp)
|
if tp.is_raw_function:
|
||||||
|
tp = self._get_type_pointer(tp, quals)
|
||||||
|
self._declare('function ' + decl.name, tp)
|
||||||
|
elif (tp.is_integer_type() and
|
||||||
|
hasattr(decl, 'init') and
|
||||||
|
hasattr(decl.init, 'value') and
|
||||||
|
_r_int_literal.match(decl.init.value)):
|
||||||
|
self._add_integer_constant(decl.name, decl.init.value)
|
||||||
|
elif (tp.is_integer_type() and
|
||||||
|
isinstance(decl.init, pycparser.c_ast.UnaryOp) and
|
||||||
|
decl.init.op == '-' and
|
||||||
|
hasattr(decl.init.expr, 'value') and
|
||||||
|
_r_int_literal.match(decl.init.expr.value)):
|
||||||
|
self._add_integer_constant(decl.name,
|
||||||
|
'-' + decl.init.expr.value)
|
||||||
|
elif (quals & model.Q_CONST) and not tp.is_array_type:
|
||||||
|
self._declare('constant ' + decl.name, tp, quals=quals)
|
||||||
else:
|
else:
|
||||||
self._declare('variable ' + decl.name, tp)
|
self._declare('variable ' + decl.name, tp, quals=quals)
|
||||||
|
|
||||||
def parse_type(self, cdecl):
|
def parse_type(self, cdecl):
|
||||||
ast, macros = self._parse('void __dummy(\n%s\n);' % cdecl)[:2]
|
ast, macros = self._parse('void __dummy(\n%s\n);' % cdecl)[:2]
|
||||||
|
@ -270,34 +325,51 @@ class Parser(object):
|
||||||
exprnode = ast.ext[-1].type.args.params[0]
|
exprnode = ast.ext[-1].type.args.params[0]
|
||||||
if isinstance(exprnode, pycparser.c_ast.ID):
|
if isinstance(exprnode, pycparser.c_ast.ID):
|
||||||
raise api.CDefError("unknown identifier '%s'" % (exprnode.name,))
|
raise api.CDefError("unknown identifier '%s'" % (exprnode.name,))
|
||||||
return self._get_type(exprnode.type)
|
tp, quals = self._get_type_and_quals(exprnode.type)
|
||||||
|
return tp
|
||||||
|
|
||||||
def _declare(self, name, obj):
|
def _declare(self, name, obj, included=False, quals=0):
|
||||||
if name in self._declarations:
|
if name in self._declarations:
|
||||||
if self._declarations[name] is obj:
|
prevobj, prevquals = self._declarations[name]
|
||||||
|
if prevobj is obj and prevquals == quals:
|
||||||
return
|
return
|
||||||
if not self._override:
|
if not self._override:
|
||||||
raise api.FFIError(
|
raise api.FFIError(
|
||||||
"multiple declarations of %s (for interactive usage, "
|
"multiple declarations of %s (for interactive usage, "
|
||||||
"try cdef(xx, override=True))" % (name,))
|
"try cdef(xx, override=True))" % (name,))
|
||||||
assert '__dotdotdot__' not in name.split()
|
assert '__dotdotdot__' not in name.split()
|
||||||
self._declarations[name] = obj
|
self._declarations[name] = (obj, quals)
|
||||||
|
if included:
|
||||||
|
self._included_declarations.add(obj)
|
||||||
|
|
||||||
def _get_type_pointer(self, type, const=False):
|
def _extract_quals(self, type):
|
||||||
|
quals = 0
|
||||||
|
if isinstance(type, (pycparser.c_ast.TypeDecl,
|
||||||
|
pycparser.c_ast.PtrDecl)):
|
||||||
|
if 'const' in type.quals:
|
||||||
|
quals |= model.Q_CONST
|
||||||
|
if 'restrict' in type.quals:
|
||||||
|
quals |= model.Q_RESTRICT
|
||||||
|
return quals
|
||||||
|
|
||||||
|
def _get_type_pointer(self, type, quals, declname=None):
|
||||||
if isinstance(type, model.RawFunctionType):
|
if isinstance(type, model.RawFunctionType):
|
||||||
return type.as_function_pointer()
|
return type.as_function_pointer()
|
||||||
if const:
|
if (isinstance(type, model.StructOrUnionOrEnum) and
|
||||||
return model.ConstPointerType(type)
|
type.name.startswith('$') and type.name[1:].isdigit() and
|
||||||
return model.PointerType(type)
|
type.forcename is None and declname is not None):
|
||||||
|
return model.NamedPointerType(type, declname, quals)
|
||||||
|
return model.PointerType(type, quals)
|
||||||
|
|
||||||
def _get_type(self, typenode, name=None, partial_length_ok=False):
|
def _get_type_and_quals(self, typenode, name=None, partial_length_ok=False):
|
||||||
# first, dereference typedefs, if we have it already parsed, we're good
|
# first, dereference typedefs, if we have it already parsed, we're good
|
||||||
if (isinstance(typenode, pycparser.c_ast.TypeDecl) and
|
if (isinstance(typenode, pycparser.c_ast.TypeDecl) and
|
||||||
isinstance(typenode.type, pycparser.c_ast.IdentifierType) and
|
isinstance(typenode.type, pycparser.c_ast.IdentifierType) and
|
||||||
len(typenode.type.names) == 1 and
|
len(typenode.type.names) == 1 and
|
||||||
('typedef ' + typenode.type.names[0]) in self._declarations):
|
('typedef ' + typenode.type.names[0]) in self._declarations):
|
||||||
type = self._declarations['typedef ' + typenode.type.names[0]]
|
tp, quals = self._declarations['typedef ' + typenode.type.names[0]]
|
||||||
return type
|
quals |= self._extract_quals(typenode)
|
||||||
|
return tp, quals
|
||||||
#
|
#
|
||||||
if isinstance(typenode, pycparser.c_ast.ArrayDecl):
|
if isinstance(typenode, pycparser.c_ast.ArrayDecl):
|
||||||
# array type
|
# array type
|
||||||
|
@ -306,15 +378,19 @@ class Parser(object):
|
||||||
else:
|
else:
|
||||||
length = self._parse_constant(
|
length = self._parse_constant(
|
||||||
typenode.dim, partial_length_ok=partial_length_ok)
|
typenode.dim, partial_length_ok=partial_length_ok)
|
||||||
return model.ArrayType(self._get_type(typenode.type), length)
|
tp, quals = self._get_type_and_quals(typenode.type,
|
||||||
|
partial_length_ok=partial_length_ok)
|
||||||
|
return model.ArrayType(tp, length), quals
|
||||||
#
|
#
|
||||||
if isinstance(typenode, pycparser.c_ast.PtrDecl):
|
if isinstance(typenode, pycparser.c_ast.PtrDecl):
|
||||||
# pointer type
|
# pointer type
|
||||||
const = (isinstance(typenode.type, pycparser.c_ast.TypeDecl)
|
itemtype, itemquals = self._get_type_and_quals(typenode.type)
|
||||||
and 'const' in typenode.type.quals)
|
tp = self._get_type_pointer(itemtype, itemquals, declname=name)
|
||||||
return self._get_type_pointer(self._get_type(typenode.type), const)
|
quals = self._extract_quals(typenode)
|
||||||
|
return tp, quals
|
||||||
#
|
#
|
||||||
if isinstance(typenode, pycparser.c_ast.TypeDecl):
|
if isinstance(typenode, pycparser.c_ast.TypeDecl):
|
||||||
|
quals = self._extract_quals(typenode)
|
||||||
type = typenode.type
|
type = typenode.type
|
||||||
if isinstance(type, pycparser.c_ast.IdentifierType):
|
if isinstance(type, pycparser.c_ast.IdentifierType):
|
||||||
# assume a primitive type. get it from .names, but reduce
|
# assume a primitive type. get it from .names, but reduce
|
||||||
|
@ -342,35 +418,38 @@ class Parser(object):
|
||||||
names = newnames + names
|
names = newnames + names
|
||||||
ident = ' '.join(names)
|
ident = ' '.join(names)
|
||||||
if ident == 'void':
|
if ident == 'void':
|
||||||
return model.void_type
|
return model.void_type, quals
|
||||||
if ident == '__dotdotdot__':
|
if ident == '__dotdotdot__':
|
||||||
raise api.FFIError(':%d: bad usage of "..."' %
|
raise api.FFIError(':%d: bad usage of "..."' %
|
||||||
typenode.coord.line)
|
typenode.coord.line)
|
||||||
return resolve_common_type(ident)
|
return resolve_common_type(ident), quals
|
||||||
#
|
#
|
||||||
if isinstance(type, pycparser.c_ast.Struct):
|
if isinstance(type, pycparser.c_ast.Struct):
|
||||||
# 'struct foobar'
|
# 'struct foobar'
|
||||||
return self._get_struct_union_enum_type('struct', type, name)
|
tp = self._get_struct_union_enum_type('struct', type, name)
|
||||||
|
return tp, quals
|
||||||
#
|
#
|
||||||
if isinstance(type, pycparser.c_ast.Union):
|
if isinstance(type, pycparser.c_ast.Union):
|
||||||
# 'union foobar'
|
# 'union foobar'
|
||||||
return self._get_struct_union_enum_type('union', type, name)
|
tp = self._get_struct_union_enum_type('union', type, name)
|
||||||
|
return tp, quals
|
||||||
#
|
#
|
||||||
if isinstance(type, pycparser.c_ast.Enum):
|
if isinstance(type, pycparser.c_ast.Enum):
|
||||||
# 'enum foobar'
|
# 'enum foobar'
|
||||||
return self._get_struct_union_enum_type('enum', type, name)
|
tp = self._get_struct_union_enum_type('enum', type, name)
|
||||||
|
return tp, quals
|
||||||
#
|
#
|
||||||
if isinstance(typenode, pycparser.c_ast.FuncDecl):
|
if isinstance(typenode, pycparser.c_ast.FuncDecl):
|
||||||
# a function type
|
# a function type
|
||||||
return self._parse_function_type(typenode, name)
|
return self._parse_function_type(typenode, name), 0
|
||||||
#
|
#
|
||||||
# nested anonymous structs or unions end up here
|
# nested anonymous structs or unions end up here
|
||||||
if isinstance(typenode, pycparser.c_ast.Struct):
|
if isinstance(typenode, pycparser.c_ast.Struct):
|
||||||
return self._get_struct_union_enum_type('struct', typenode, name,
|
return self._get_struct_union_enum_type('struct', typenode, name,
|
||||||
nested=True)
|
nested=True), 0
|
||||||
if isinstance(typenode, pycparser.c_ast.Union):
|
if isinstance(typenode, pycparser.c_ast.Union):
|
||||||
return self._get_struct_union_enum_type('union', typenode, name,
|
return self._get_struct_union_enum_type('union', typenode, name,
|
||||||
nested=True)
|
nested=True), 0
|
||||||
#
|
#
|
||||||
raise api.FFIError(":%d: bad or unsupported type declaration" %
|
raise api.FFIError(":%d: bad or unsupported type declaration" %
|
||||||
typenode.coord.line)
|
typenode.coord.line)
|
||||||
|
@ -389,31 +468,28 @@ class Parser(object):
|
||||||
raise api.CDefError(
|
raise api.CDefError(
|
||||||
"%s: a function with only '(...)' as argument"
|
"%s: a function with only '(...)' as argument"
|
||||||
" is not correct C" % (funcname or 'in expression'))
|
" is not correct C" % (funcname or 'in expression'))
|
||||||
elif (len(params) == 1 and
|
args = [self._as_func_arg(*self._get_type_and_quals(argdeclnode.type))
|
||||||
isinstance(params[0].type, pycparser.c_ast.TypeDecl) and
|
|
||||||
isinstance(params[0].type.type, pycparser.c_ast.IdentifierType)
|
|
||||||
and list(params[0].type.type.names) == ['void']):
|
|
||||||
del params[0]
|
|
||||||
args = [self._as_func_arg(self._get_type(argdeclnode.type))
|
|
||||||
for argdeclnode in params]
|
for argdeclnode in params]
|
||||||
result = self._get_type(typenode.type)
|
if not ellipsis and args == [model.void_type]:
|
||||||
return model.RawFunctionType(tuple(args), result, ellipsis)
|
args = []
|
||||||
|
result, quals = self._get_type_and_quals(typenode.type)
|
||||||
|
# the 'quals' on the result type are ignored. HACK: we absure them
|
||||||
|
# to detect __stdcall functions: we textually replace "__stdcall"
|
||||||
|
# with "volatile volatile const" above.
|
||||||
|
abi = None
|
||||||
|
if hasattr(typenode.type, 'quals'): # else, probable syntax error anyway
|
||||||
|
if typenode.type.quals[-3:] == ['volatile', 'volatile', 'const']:
|
||||||
|
abi = '__stdcall'
|
||||||
|
return model.RawFunctionType(tuple(args), result, ellipsis, abi)
|
||||||
|
|
||||||
def _as_func_arg(self, type):
|
def _as_func_arg(self, type, quals):
|
||||||
if isinstance(type, model.ArrayType):
|
if isinstance(type, model.ArrayType):
|
||||||
return model.PointerType(type.item)
|
return model.PointerType(type.item, quals)
|
||||||
elif isinstance(type, model.RawFunctionType):
|
elif isinstance(type, model.RawFunctionType):
|
||||||
return type.as_function_pointer()
|
return type.as_function_pointer()
|
||||||
else:
|
else:
|
||||||
return type
|
return type
|
||||||
|
|
||||||
def _is_constant_globalvar(self, typenode):
|
|
||||||
if isinstance(typenode, pycparser.c_ast.PtrDecl):
|
|
||||||
return 'const' in typenode.quals
|
|
||||||
if isinstance(typenode, pycparser.c_ast.TypeDecl):
|
|
||||||
return 'const' in typenode.quals
|
|
||||||
return False
|
|
||||||
|
|
||||||
def _get_struct_union_enum_type(self, kind, type, name=None, nested=False):
|
def _get_struct_union_enum_type(self, kind, type, name=None, nested=False):
|
||||||
# First, a level of caching on the exact 'type' node of the AST.
|
# First, a level of caching on the exact 'type' node of the AST.
|
||||||
# This is obscure, but needed because pycparser "unrolls" declarations
|
# This is obscure, but needed because pycparser "unrolls" declarations
|
||||||
|
@ -452,7 +528,7 @@ class Parser(object):
|
||||||
else:
|
else:
|
||||||
explicit_name = name
|
explicit_name = name
|
||||||
key = '%s %s' % (kind, name)
|
key = '%s %s' % (kind, name)
|
||||||
tp = self._declarations.get(key, None)
|
tp, _ = self._declarations.get(key, (None, None))
|
||||||
#
|
#
|
||||||
if tp is None:
|
if tp is None:
|
||||||
if kind == 'struct':
|
if kind == 'struct':
|
||||||
|
@ -460,6 +536,8 @@ class Parser(object):
|
||||||
elif kind == 'union':
|
elif kind == 'union':
|
||||||
tp = model.UnionType(explicit_name, None, None, None)
|
tp = model.UnionType(explicit_name, None, None, None)
|
||||||
elif kind == 'enum':
|
elif kind == 'enum':
|
||||||
|
if explicit_name == '__dotdotdot__':
|
||||||
|
raise CDefError("Enums cannot be declared with ...")
|
||||||
tp = self._build_enum_type(explicit_name, type.values)
|
tp = self._build_enum_type(explicit_name, type.values)
|
||||||
else:
|
else:
|
||||||
raise AssertionError("kind = %r" % (kind,))
|
raise AssertionError("kind = %r" % (kind,))
|
||||||
|
@ -492,6 +570,7 @@ class Parser(object):
|
||||||
fldnames = []
|
fldnames = []
|
||||||
fldtypes = []
|
fldtypes = []
|
||||||
fldbitsize = []
|
fldbitsize = []
|
||||||
|
fldquals = []
|
||||||
for decl in type.decls:
|
for decl in type.decls:
|
||||||
if (isinstance(decl.type, pycparser.c_ast.IdentifierType) and
|
if (isinstance(decl.type, pycparser.c_ast.IdentifierType) and
|
||||||
''.join(decl.type.names) == '__dotdotdot__'):
|
''.join(decl.type.names) == '__dotdotdot__'):
|
||||||
|
@ -505,7 +584,8 @@ class Parser(object):
|
||||||
else:
|
else:
|
||||||
bitsize = self._parse_constant(decl.bitsize)
|
bitsize = self._parse_constant(decl.bitsize)
|
||||||
self._partial_length = False
|
self._partial_length = False
|
||||||
type = self._get_type(decl.type, partial_length_ok=True)
|
type, fqual = self._get_type_and_quals(decl.type,
|
||||||
|
partial_length_ok=True)
|
||||||
if self._partial_length:
|
if self._partial_length:
|
||||||
self._make_partial(tp, nested)
|
self._make_partial(tp, nested)
|
||||||
if isinstance(type, model.StructType) and type.partial:
|
if isinstance(type, model.StructType) and type.partial:
|
||||||
|
@ -513,14 +593,19 @@ class Parser(object):
|
||||||
fldnames.append(decl.name or '')
|
fldnames.append(decl.name or '')
|
||||||
fldtypes.append(type)
|
fldtypes.append(type)
|
||||||
fldbitsize.append(bitsize)
|
fldbitsize.append(bitsize)
|
||||||
|
fldquals.append(fqual)
|
||||||
tp.fldnames = tuple(fldnames)
|
tp.fldnames = tuple(fldnames)
|
||||||
tp.fldtypes = tuple(fldtypes)
|
tp.fldtypes = tuple(fldtypes)
|
||||||
tp.fldbitsize = tuple(fldbitsize)
|
tp.fldbitsize = tuple(fldbitsize)
|
||||||
|
tp.fldquals = tuple(fldquals)
|
||||||
if fldbitsize != [-1] * len(fldbitsize):
|
if fldbitsize != [-1] * len(fldbitsize):
|
||||||
if isinstance(tp, model.StructType) and tp.partial:
|
if isinstance(tp, model.StructType) and tp.partial:
|
||||||
raise NotImplementedError("%s: using both bitfields and '...;'"
|
raise NotImplementedError("%s: using both bitfields and '...;'"
|
||||||
% (tp,))
|
% (tp,))
|
||||||
tp.packed = self._packed
|
tp.packed = self._packed
|
||||||
|
if tp.completed: # must be re-completed: it is not opaque any more
|
||||||
|
tp.completed = 0
|
||||||
|
self._recomplete.append(tp)
|
||||||
return tp
|
return tp
|
||||||
|
|
||||||
def _make_partial(self, tp, nested):
|
def _make_partial(self, tp, nested):
|
||||||
|
@ -532,9 +617,24 @@ class Parser(object):
|
||||||
|
|
||||||
def _parse_constant(self, exprnode, partial_length_ok=False):
|
def _parse_constant(self, exprnode, partial_length_ok=False):
|
||||||
# for now, limited to expressions that are an immediate number
|
# for now, limited to expressions that are an immediate number
|
||||||
# or negative number
|
# or positive/negative number
|
||||||
if isinstance(exprnode, pycparser.c_ast.Constant):
|
if isinstance(exprnode, pycparser.c_ast.Constant):
|
||||||
return int(exprnode.value, 0)
|
s = exprnode.value
|
||||||
|
if s.startswith('0'):
|
||||||
|
if s.startswith('0x') or s.startswith('0X'):
|
||||||
|
return int(s, 16)
|
||||||
|
return int(s, 8)
|
||||||
|
elif '1' <= s[0] <= '9':
|
||||||
|
return int(s, 10)
|
||||||
|
elif s[0] == "'" and s[-1] == "'" and (
|
||||||
|
len(s) == 3 or (len(s) == 4 and s[1] == "\\")):
|
||||||
|
return ord(s[-2])
|
||||||
|
else:
|
||||||
|
raise api.CDefError("invalid constant %r" % (s,))
|
||||||
|
#
|
||||||
|
if (isinstance(exprnode, pycparser.c_ast.UnaryOp) and
|
||||||
|
exprnode.op == '+'):
|
||||||
|
return self._parse_constant(exprnode.expr)
|
||||||
#
|
#
|
||||||
if (isinstance(exprnode, pycparser.c_ast.UnaryOp) and
|
if (isinstance(exprnode, pycparser.c_ast.UnaryOp) and
|
||||||
exprnode.op == '-'):
|
exprnode.op == '-'):
|
||||||
|
@ -555,19 +655,21 @@ class Parser(object):
|
||||||
|
|
||||||
def _build_enum_type(self, explicit_name, decls):
|
def _build_enum_type(self, explicit_name, decls):
|
||||||
if decls is not None:
|
if decls is not None:
|
||||||
enumerators1 = [enum.name for enum in decls.enumerators]
|
partial = False
|
||||||
enumerators = [s for s in enumerators1
|
enumerators = []
|
||||||
if not _r_enum_dotdotdot.match(s)]
|
|
||||||
partial = len(enumerators) < len(enumerators1)
|
|
||||||
enumerators = tuple(enumerators)
|
|
||||||
enumvalues = []
|
enumvalues = []
|
||||||
nextenumvalue = 0
|
nextenumvalue = 0
|
||||||
for enum in decls.enumerators[:len(enumerators)]:
|
for enum in decls.enumerators:
|
||||||
|
if _r_enum_dotdotdot.match(enum.name):
|
||||||
|
partial = True
|
||||||
|
continue
|
||||||
if enum.value is not None:
|
if enum.value is not None:
|
||||||
nextenumvalue = self._parse_constant(enum.value)
|
nextenumvalue = self._parse_constant(enum.value)
|
||||||
|
enumerators.append(enum.name)
|
||||||
enumvalues.append(nextenumvalue)
|
enumvalues.append(nextenumvalue)
|
||||||
self._add_constants(enum.name, nextenumvalue)
|
self._add_constants(enum.name, nextenumvalue)
|
||||||
nextenumvalue += 1
|
nextenumvalue += 1
|
||||||
|
enumerators = tuple(enumerators)
|
||||||
enumvalues = tuple(enumvalues)
|
enumvalues = tuple(enumvalues)
|
||||||
tp = model.EnumType(explicit_name, enumerators, enumvalues)
|
tp = model.EnumType(explicit_name, enumerators, enumvalues)
|
||||||
tp.partial = partial
|
tp.partial = partial
|
||||||
|
@ -576,9 +678,35 @@ class Parser(object):
|
||||||
return tp
|
return tp
|
||||||
|
|
||||||
def include(self, other):
|
def include(self, other):
|
||||||
for name, tp in other._declarations.items():
|
for name, (tp, quals) in other._declarations.items():
|
||||||
|
if name.startswith('anonymous $enum_$'):
|
||||||
|
continue # fix for test_anonymous_enum_include
|
||||||
kind = name.split(' ', 1)[0]
|
kind = name.split(' ', 1)[0]
|
||||||
if kind in ('typedef', 'struct', 'union', 'enum'):
|
if kind in ('struct', 'union', 'enum', 'anonymous', 'typedef'):
|
||||||
self._declare(name, tp)
|
self._declare(name, tp, included=True, quals=quals)
|
||||||
for k, v in other._int_constants.items():
|
for k, v in other._int_constants.items():
|
||||||
self._add_constants(k, v)
|
self._add_constants(k, v)
|
||||||
|
|
||||||
|
def _get_unknown_type(self, decl):
|
||||||
|
typenames = decl.type.type.names
|
||||||
|
assert typenames[-1] == '__dotdotdot__'
|
||||||
|
if len(typenames) == 1:
|
||||||
|
return model.unknown_type(decl.name)
|
||||||
|
|
||||||
|
if (typenames[:-1] == ['float'] or
|
||||||
|
typenames[:-1] == ['double']):
|
||||||
|
# not for 'long double' so far
|
||||||
|
result = model.UnknownFloatType(decl.name)
|
||||||
|
else:
|
||||||
|
for t in typenames[:-1]:
|
||||||
|
if t not in ['int', 'short', 'long', 'signed',
|
||||||
|
'unsigned', 'char']:
|
||||||
|
raise api.FFIError(':%d: bad usage of "..."' %
|
||||||
|
decl.coord.line)
|
||||||
|
result = model.UnknownIntegerType(decl.name)
|
||||||
|
|
||||||
|
if self._uses_new_feature is None:
|
||||||
|
self._uses_new_feature = "'typedef %s... %s'" % (
|
||||||
|
' '.join(typenames[:-1]), decl.name)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import os
|
import sys, os
|
||||||
|
|
||||||
|
|
||||||
class VerificationError(Exception):
|
class VerificationError(Exception):
|
||||||
|
@ -11,6 +11,9 @@ class VerificationMissing(Exception):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
LIST_OF_FILE_NAMES = ['sources', 'include_dirs', 'library_dirs',
|
||||||
|
'extra_objects', 'depends']
|
||||||
|
|
||||||
def get_extension(srcfilename, modname, sources=(), **kwds):
|
def get_extension(srcfilename, modname, sources=(), **kwds):
|
||||||
from distutils.core import Extension
|
from distutils.core import Extension
|
||||||
allsources = [srcfilename]
|
allsources = [srcfilename]
|
||||||
|
|
|
@ -2,18 +2,21 @@ from weakref import ref
|
||||||
|
|
||||||
|
|
||||||
class GcWeakrefs(object):
|
class GcWeakrefs(object):
|
||||||
# code copied and adapted from WeakKeyDictionary.
|
|
||||||
|
|
||||||
def __init__(self, ffi):
|
def __init__(self, ffi):
|
||||||
self.ffi = ffi
|
self.ffi = ffi
|
||||||
self.data = data = {}
|
self.data = {}
|
||||||
def remove(k):
|
|
||||||
destructor, cdata = data.pop(k)
|
|
||||||
destructor(cdata)
|
|
||||||
self.remove = remove
|
|
||||||
|
|
||||||
def build(self, cdata, destructor):
|
def build(self, cdata, destructor):
|
||||||
# make a new cdata of the same type as the original one
|
# make a new cdata of the same type as the original one
|
||||||
new_cdata = self.ffi.cast(self.ffi._backend.typeof(cdata), cdata)
|
new_cdata = self.ffi.cast(self.ffi._backend.typeof(cdata), cdata)
|
||||||
self.data[ref(new_cdata, self.remove)] = destructor, cdata
|
#
|
||||||
|
def remove(key):
|
||||||
|
# careful, this function is not protected by any lock
|
||||||
|
old_key = self.data.pop(index)
|
||||||
|
assert old_key is key
|
||||||
|
destructor(cdata)
|
||||||
|
#
|
||||||
|
key = ref(new_cdata, remove)
|
||||||
|
index = object()
|
||||||
|
self.data[index] = key
|
||||||
return new_cdata
|
return new_cdata
|
||||||
|
|
|
@ -1,14 +1,29 @@
|
||||||
import types
|
import types, sys
|
||||||
import weakref
|
import weakref
|
||||||
|
|
||||||
from .lock import allocate_lock
|
from .lock import allocate_lock
|
||||||
|
|
||||||
|
|
||||||
|
# type qualifiers
|
||||||
|
Q_CONST = 0x01
|
||||||
|
Q_RESTRICT = 0x02
|
||||||
|
|
||||||
|
def qualify(quals, replace_with):
|
||||||
|
if quals & Q_CONST:
|
||||||
|
replace_with = ' const ' + replace_with.lstrip()
|
||||||
|
if quals & Q_RESTRICT:
|
||||||
|
# It seems that __restrict is supported by gcc and msvc.
|
||||||
|
# If you hit some different compiler, add a #define in
|
||||||
|
# _cffi_include.h for it (and in its copies, documented there)
|
||||||
|
replace_with = ' __restrict ' + replace_with.lstrip()
|
||||||
|
return replace_with
|
||||||
|
|
||||||
|
|
||||||
class BaseTypeByIdentity(object):
|
class BaseTypeByIdentity(object):
|
||||||
is_array_type = False
|
is_array_type = False
|
||||||
is_raw_function = False
|
is_raw_function = False
|
||||||
|
|
||||||
def get_c_name(self, replace_with='', context='a C file'):
|
def get_c_name(self, replace_with='', context='a C file', quals=0):
|
||||||
result = self.c_name_with_marker
|
result = self.c_name_with_marker
|
||||||
assert result.count('&') == 1
|
assert result.count('&') == 1
|
||||||
# some logic duplication with ffi.getctype()... :-(
|
# some logic duplication with ffi.getctype()... :-(
|
||||||
|
@ -18,6 +33,7 @@ class BaseTypeByIdentity(object):
|
||||||
replace_with = '(%s)' % replace_with
|
replace_with = '(%s)' % replace_with
|
||||||
elif not replace_with[0] in '[(':
|
elif not replace_with[0] in '[(':
|
||||||
replace_with = ' ' + replace_with
|
replace_with = ' ' + replace_with
|
||||||
|
replace_with = qualify(quals, replace_with)
|
||||||
result = result.replace('&', replace_with)
|
result = result.replace('&', replace_with)
|
||||||
if '$' in result:
|
if '$' in result:
|
||||||
from .ffiplatform import VerificationError
|
from .ffiplatform import VerificationError
|
||||||
|
@ -32,6 +48,9 @@ class BaseTypeByIdentity(object):
|
||||||
def has_c_name(self):
|
def has_c_name(self):
|
||||||
return '$' not in self._get_c_name()
|
return '$' not in self._get_c_name()
|
||||||
|
|
||||||
|
def is_integer_type(self):
|
||||||
|
return False
|
||||||
|
|
||||||
def get_cached_btype(self, ffi, finishlist, can_delay=False):
|
def get_cached_btype(self, ffi, finishlist, can_delay=False):
|
||||||
try:
|
try:
|
||||||
BType = ffi._cached_btypes[self]
|
BType = ffi._cached_btypes[self]
|
||||||
|
@ -73,7 +92,11 @@ class VoidType(BaseType):
|
||||||
void_type = VoidType()
|
void_type = VoidType()
|
||||||
|
|
||||||
|
|
||||||
class PrimitiveType(BaseType):
|
class BasePrimitiveType(BaseType):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class PrimitiveType(BasePrimitiveType):
|
||||||
_attrs_ = ('name',)
|
_attrs_ = ('name',)
|
||||||
|
|
||||||
ALL_PRIMITIVE_TYPES = {
|
ALL_PRIMITIVE_TYPES = {
|
||||||
|
@ -102,8 +125,26 @@ class PrimitiveType(BaseType):
|
||||||
'uint32_t': 'i',
|
'uint32_t': 'i',
|
||||||
'int64_t': 'i',
|
'int64_t': 'i',
|
||||||
'uint64_t': 'i',
|
'uint64_t': 'i',
|
||||||
|
'int_least8_t': 'i',
|
||||||
|
'uint_least8_t': 'i',
|
||||||
|
'int_least16_t': 'i',
|
||||||
|
'uint_least16_t': 'i',
|
||||||
|
'int_least32_t': 'i',
|
||||||
|
'uint_least32_t': 'i',
|
||||||
|
'int_least64_t': 'i',
|
||||||
|
'uint_least64_t': 'i',
|
||||||
|
'int_fast8_t': 'i',
|
||||||
|
'uint_fast8_t': 'i',
|
||||||
|
'int_fast16_t': 'i',
|
||||||
|
'uint_fast16_t': 'i',
|
||||||
|
'int_fast32_t': 'i',
|
||||||
|
'uint_fast32_t': 'i',
|
||||||
|
'int_fast64_t': 'i',
|
||||||
|
'uint_fast64_t': 'i',
|
||||||
'intptr_t': 'i',
|
'intptr_t': 'i',
|
||||||
'uintptr_t': 'i',
|
'uintptr_t': 'i',
|
||||||
|
'intmax_t': 'i',
|
||||||
|
'uintmax_t': 'i',
|
||||||
'ptrdiff_t': 'i',
|
'ptrdiff_t': 'i',
|
||||||
'size_t': 'i',
|
'size_t': 'i',
|
||||||
'ssize_t': 'i',
|
'ssize_t': 'i',
|
||||||
|
@ -125,19 +166,48 @@ class PrimitiveType(BaseType):
|
||||||
return global_cache(self, ffi, 'new_primitive_type', self.name)
|
return global_cache(self, ffi, 'new_primitive_type', self.name)
|
||||||
|
|
||||||
|
|
||||||
class BaseFunctionType(BaseType):
|
class UnknownIntegerType(BasePrimitiveType):
|
||||||
_attrs_ = ('args', 'result', 'ellipsis')
|
_attrs_ = ('name',)
|
||||||
|
|
||||||
def __init__(self, args, result, ellipsis):
|
def __init__(self, name):
|
||||||
|
self.name = name
|
||||||
|
self.c_name_with_marker = name + '&'
|
||||||
|
|
||||||
|
def is_integer_type(self):
|
||||||
|
return True
|
||||||
|
|
||||||
|
def build_backend_type(self, ffi, finishlist):
|
||||||
|
raise NotImplementedError("integer type '%s' can only be used after "
|
||||||
|
"compilation" % self.name)
|
||||||
|
|
||||||
|
class UnknownFloatType(BasePrimitiveType):
|
||||||
|
_attrs_ = ('name', )
|
||||||
|
|
||||||
|
def __init__(self, name):
|
||||||
|
self.name = name
|
||||||
|
self.c_name_with_marker = name + '&'
|
||||||
|
|
||||||
|
def build_backend_type(self, ffi, finishlist):
|
||||||
|
raise NotImplementedError("float type '%s' can only be used after "
|
||||||
|
"compilation" % self.name)
|
||||||
|
|
||||||
|
|
||||||
|
class BaseFunctionType(BaseType):
|
||||||
|
_attrs_ = ('args', 'result', 'ellipsis', 'abi')
|
||||||
|
|
||||||
|
def __init__(self, args, result, ellipsis, abi=None):
|
||||||
self.args = args
|
self.args = args
|
||||||
self.result = result
|
self.result = result
|
||||||
self.ellipsis = ellipsis
|
self.ellipsis = ellipsis
|
||||||
|
self.abi = abi
|
||||||
#
|
#
|
||||||
reprargs = [arg._get_c_name() for arg in self.args]
|
reprargs = [arg._get_c_name() for arg in self.args]
|
||||||
if self.ellipsis:
|
if self.ellipsis:
|
||||||
reprargs.append('...')
|
reprargs.append('...')
|
||||||
reprargs = reprargs or ['void']
|
reprargs = reprargs or ['void']
|
||||||
replace_with = self._base_pattern % (', '.join(reprargs),)
|
replace_with = self._base_pattern % (', '.join(reprargs),)
|
||||||
|
if abi is not None:
|
||||||
|
replace_with = replace_with[:1] + abi + ' ' + replace_with[1:]
|
||||||
self.c_name_with_marker = (
|
self.c_name_with_marker = (
|
||||||
self.result.c_name_with_marker.replace('&', replace_with))
|
self.result.c_name_with_marker.replace('&', replace_with))
|
||||||
|
|
||||||
|
@ -155,7 +225,7 @@ class RawFunctionType(BaseFunctionType):
|
||||||
"type, not a pointer-to-function type" % (self,))
|
"type, not a pointer-to-function type" % (self,))
|
||||||
|
|
||||||
def as_function_pointer(self):
|
def as_function_pointer(self):
|
||||||
return FunctionPtrType(self.args, self.result, self.ellipsis)
|
return FunctionPtrType(self.args, self.result, self.ellipsis, self.abi)
|
||||||
|
|
||||||
|
|
||||||
class FunctionPtrType(BaseFunctionType):
|
class FunctionPtrType(BaseFunctionType):
|
||||||
|
@ -166,21 +236,29 @@ class FunctionPtrType(BaseFunctionType):
|
||||||
args = []
|
args = []
|
||||||
for tp in self.args:
|
for tp in self.args:
|
||||||
args.append(tp.get_cached_btype(ffi, finishlist))
|
args.append(tp.get_cached_btype(ffi, finishlist))
|
||||||
|
abi_args = ()
|
||||||
|
if self.abi == "__stdcall":
|
||||||
|
if not self.ellipsis: # __stdcall ignored for variadic funcs
|
||||||
|
try:
|
||||||
|
abi_args = (ffi._backend.FFI_STDCALL,)
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
return global_cache(self, ffi, 'new_function_type',
|
return global_cache(self, ffi, 'new_function_type',
|
||||||
tuple(args), result, self.ellipsis)
|
tuple(args), result, self.ellipsis, *abi_args)
|
||||||
|
|
||||||
|
def as_raw_function(self):
|
||||||
|
return RawFunctionType(self.args, self.result, self.ellipsis, self.abi)
|
||||||
|
|
||||||
|
|
||||||
class PointerType(BaseType):
|
class PointerType(BaseType):
|
||||||
_attrs_ = ('totype',)
|
_attrs_ = ('totype', 'quals')
|
||||||
_base_pattern = " *&"
|
|
||||||
_base_pattern_array = "(*&)"
|
|
||||||
|
|
||||||
def __init__(self, totype):
|
def __init__(self, totype, quals=0):
|
||||||
self.totype = totype
|
self.totype = totype
|
||||||
|
self.quals = quals
|
||||||
|
extra = qualify(quals, " *&")
|
||||||
if totype.is_array_type:
|
if totype.is_array_type:
|
||||||
extra = self._base_pattern_array
|
extra = "(%s)" % (extra.lstrip(),)
|
||||||
else:
|
|
||||||
extra = self._base_pattern
|
|
||||||
self.c_name_with_marker = totype.c_name_with_marker.replace('&', extra)
|
self.c_name_with_marker = totype.c_name_with_marker.replace('&', extra)
|
||||||
|
|
||||||
def build_backend_type(self, ffi, finishlist):
|
def build_backend_type(self, ffi, finishlist):
|
||||||
|
@ -189,10 +267,8 @@ class PointerType(BaseType):
|
||||||
|
|
||||||
voidp_type = PointerType(void_type)
|
voidp_type = PointerType(void_type)
|
||||||
|
|
||||||
|
def ConstPointerType(totype):
|
||||||
class ConstPointerType(PointerType):
|
return PointerType(totype, Q_CONST)
|
||||||
_base_pattern = " const *&"
|
|
||||||
_base_pattern_array = "(const *&)"
|
|
||||||
|
|
||||||
const_voidp_type = ConstPointerType(void_type)
|
const_voidp_type = ConstPointerType(void_type)
|
||||||
|
|
||||||
|
@ -200,8 +276,8 @@ const_voidp_type = ConstPointerType(void_type)
|
||||||
class NamedPointerType(PointerType):
|
class NamedPointerType(PointerType):
|
||||||
_attrs_ = ('totype', 'name')
|
_attrs_ = ('totype', 'name')
|
||||||
|
|
||||||
def __init__(self, totype, name):
|
def __init__(self, totype, name, quals=0):
|
||||||
PointerType.__init__(self, totype)
|
PointerType.__init__(self, totype, quals)
|
||||||
self.name = name
|
self.name = name
|
||||||
self.c_name_with_marker = name + '&'
|
self.c_name_with_marker = name + '&'
|
||||||
|
|
||||||
|
@ -219,7 +295,7 @@ class ArrayType(BaseType):
|
||||||
elif length == '...':
|
elif length == '...':
|
||||||
brackets = '&[/*...*/]'
|
brackets = '&[/*...*/]'
|
||||||
else:
|
else:
|
||||||
brackets = '&[%d]' % length
|
brackets = '&[%s]' % length
|
||||||
self.c_name_with_marker = (
|
self.c_name_with_marker = (
|
||||||
self.item.c_name_with_marker.replace('&', brackets))
|
self.item.c_name_with_marker.replace('&', brackets))
|
||||||
|
|
||||||
|
@ -235,6 +311,8 @@ class ArrayType(BaseType):
|
||||||
BPtrItem = PointerType(self.item).get_cached_btype(ffi, finishlist)
|
BPtrItem = PointerType(self.item).get_cached_btype(ffi, finishlist)
|
||||||
return global_cache(self, ffi, 'new_array_type', BPtrItem, self.length)
|
return global_cache(self, ffi, 'new_array_type', BPtrItem, self.length)
|
||||||
|
|
||||||
|
char_array_type = ArrayType(PrimitiveType('char'), None)
|
||||||
|
|
||||||
|
|
||||||
class StructOrUnionOrEnum(BaseTypeByIdentity):
|
class StructOrUnionOrEnum(BaseTypeByIdentity):
|
||||||
_attrs_ = ('name',)
|
_attrs_ = ('name',)
|
||||||
|
@ -255,26 +333,38 @@ class StructOrUnionOrEnum(BaseTypeByIdentity):
|
||||||
|
|
||||||
class StructOrUnion(StructOrUnionOrEnum):
|
class StructOrUnion(StructOrUnionOrEnum):
|
||||||
fixedlayout = None
|
fixedlayout = None
|
||||||
completed = False
|
completed = 0
|
||||||
partial = False
|
partial = False
|
||||||
packed = False
|
packed = False
|
||||||
|
|
||||||
def __init__(self, name, fldnames, fldtypes, fldbitsize):
|
def __init__(self, name, fldnames, fldtypes, fldbitsize, fldquals=None):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.fldnames = fldnames
|
self.fldnames = fldnames
|
||||||
self.fldtypes = fldtypes
|
self.fldtypes = fldtypes
|
||||||
self.fldbitsize = fldbitsize
|
self.fldbitsize = fldbitsize
|
||||||
|
self.fldquals = fldquals
|
||||||
self.build_c_name_with_marker()
|
self.build_c_name_with_marker()
|
||||||
|
|
||||||
|
def has_anonymous_struct_fields(self):
|
||||||
|
if self.fldtypes is None:
|
||||||
|
return False
|
||||||
|
for name, type in zip(self.fldnames, self.fldtypes):
|
||||||
|
if name == '' and isinstance(type, StructOrUnion):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
def enumfields(self):
|
def enumfields(self):
|
||||||
for name, type, bitsize in zip(self.fldnames, self.fldtypes,
|
fldquals = self.fldquals
|
||||||
self.fldbitsize):
|
if fldquals is None:
|
||||||
|
fldquals = (0,) * len(self.fldnames)
|
||||||
|
for name, type, bitsize, quals in zip(self.fldnames, self.fldtypes,
|
||||||
|
self.fldbitsize, fldquals):
|
||||||
if name == '' and isinstance(type, StructOrUnion):
|
if name == '' and isinstance(type, StructOrUnion):
|
||||||
# nested anonymous struct/union
|
# nested anonymous struct/union
|
||||||
for result in type.enumfields():
|
for result in type.enumfields():
|
||||||
yield result
|
yield result
|
||||||
else:
|
else:
|
||||||
yield (name, type, bitsize)
|
yield (name, type, bitsize, quals)
|
||||||
|
|
||||||
def force_flatten(self):
|
def force_flatten(self):
|
||||||
# force the struct or union to have a declaration that lists
|
# force the struct or union to have a declaration that lists
|
||||||
|
@ -283,13 +373,16 @@ class StructOrUnion(StructOrUnionOrEnum):
|
||||||
names = []
|
names = []
|
||||||
types = []
|
types = []
|
||||||
bitsizes = []
|
bitsizes = []
|
||||||
for name, type, bitsize in self.enumfields():
|
fldquals = []
|
||||||
|
for name, type, bitsize, quals in self.enumfields():
|
||||||
names.append(name)
|
names.append(name)
|
||||||
types.append(type)
|
types.append(type)
|
||||||
bitsizes.append(bitsize)
|
bitsizes.append(bitsize)
|
||||||
|
fldquals.append(quals)
|
||||||
self.fldnames = tuple(names)
|
self.fldnames = tuple(names)
|
||||||
self.fldtypes = tuple(types)
|
self.fldtypes = tuple(types)
|
||||||
self.fldbitsize = tuple(bitsizes)
|
self.fldbitsize = tuple(bitsizes)
|
||||||
|
self.fldquals = tuple(fldquals)
|
||||||
|
|
||||||
def get_cached_btype(self, ffi, finishlist, can_delay=False):
|
def get_cached_btype(self, ffi, finishlist, can_delay=False):
|
||||||
BType = StructOrUnionOrEnum.get_cached_btype(self, ffi, finishlist,
|
BType = StructOrUnionOrEnum.get_cached_btype(self, ffi, finishlist,
|
||||||
|
@ -305,12 +398,13 @@ class StructOrUnion(StructOrUnionOrEnum):
|
||||||
"for '%s'" % (self.name,))
|
"for '%s'" % (self.name,))
|
||||||
return
|
return
|
||||||
BType = ffi._cached_btypes[self]
|
BType = ffi._cached_btypes[self]
|
||||||
if self.fldtypes is None:
|
|
||||||
return # not completing it: it's an opaque struct
|
|
||||||
#
|
#
|
||||||
self.completed = 1
|
self.completed = 1
|
||||||
#
|
#
|
||||||
if self.fixedlayout is None:
|
if self.fldtypes is None:
|
||||||
|
pass # not completing it: it's an opaque struct
|
||||||
|
#
|
||||||
|
elif self.fixedlayout is None:
|
||||||
fldtypes = [tp.get_cached_btype(ffi, finishlist)
|
fldtypes = [tp.get_cached_btype(ffi, finishlist)
|
||||||
for tp in self.fldtypes]
|
for tp in self.fldtypes]
|
||||||
lst = list(zip(self.fldnames, fldtypes, self.fldbitsize))
|
lst = list(zip(self.fldnames, fldtypes, self.fldbitsize))
|
||||||
|
@ -449,11 +543,12 @@ def unknown_type(name, structname=None):
|
||||||
structname = '$%s' % name
|
structname = '$%s' % name
|
||||||
tp = StructType(structname, None, None, None)
|
tp = StructType(structname, None, None, None)
|
||||||
tp.force_the_name(name)
|
tp.force_the_name(name)
|
||||||
|
tp.origin = "unknown_type"
|
||||||
return tp
|
return tp
|
||||||
|
|
||||||
def unknown_ptr_type(name, structname=None):
|
def unknown_ptr_type(name, structname=None):
|
||||||
if structname is None:
|
if structname is None:
|
||||||
structname = '*$%s' % name
|
structname = '$$%s' % name
|
||||||
tp = StructType(structname, None, None, None)
|
tp = StructType(structname, None, None, None)
|
||||||
return NamedPointerType(tp, name)
|
return NamedPointerType(tp, name)
|
||||||
|
|
||||||
|
@ -478,7 +573,7 @@ def global_cache(srctype, ffi, funcname, *args, **kwds):
|
||||||
try:
|
try:
|
||||||
res = getattr(ffi._backend, funcname)(*args)
|
res = getattr(ffi._backend, funcname)(*args)
|
||||||
except NotImplementedError as e:
|
except NotImplementedError as e:
|
||||||
raise NotImplementedError("%r: %s" % (srctype, e))
|
raise NotImplementedError("%s: %r: %s" % (funcname, srctype, e))
|
||||||
# note that setdefault() on WeakValueDictionary is not atomic
|
# note that setdefault() on WeakValueDictionary is not atomic
|
||||||
# and contains a rare bug (http://bugs.python.org/issue19542);
|
# and contains a rare bug (http://bugs.python.org/issue19542);
|
||||||
# we have to use a lock and do it ourselves
|
# we have to use a lock and do it ourselves
|
||||||
|
|
167
Linux_x86_64/lib/python3.4/site-packages/cffi/parse_c_type.h
Normal file
167
Linux_x86_64/lib/python3.4/site-packages/cffi/parse_c_type.h
Normal file
|
@ -0,0 +1,167 @@
|
||||||
|
|
||||||
|
/* See doc/misc/parse_c_type.rst in the source of CFFI for more information */
|
||||||
|
|
||||||
|
typedef void *_cffi_opcode_t;
|
||||||
|
|
||||||
|
#define _CFFI_OP(opcode, arg) (_cffi_opcode_t)(opcode | (((uintptr_t)(arg)) << 8))
|
||||||
|
#define _CFFI_GETOP(cffi_opcode) ((unsigned char)(uintptr_t)cffi_opcode)
|
||||||
|
#define _CFFI_GETARG(cffi_opcode) (((intptr_t)cffi_opcode) >> 8)
|
||||||
|
|
||||||
|
#define _CFFI_OP_PRIMITIVE 1
|
||||||
|
#define _CFFI_OP_POINTER 3
|
||||||
|
#define _CFFI_OP_ARRAY 5
|
||||||
|
#define _CFFI_OP_OPEN_ARRAY 7
|
||||||
|
#define _CFFI_OP_STRUCT_UNION 9
|
||||||
|
#define _CFFI_OP_ENUM 11
|
||||||
|
#define _CFFI_OP_FUNCTION 13
|
||||||
|
#define _CFFI_OP_FUNCTION_END 15
|
||||||
|
#define _CFFI_OP_NOOP 17
|
||||||
|
#define _CFFI_OP_BITFIELD 19
|
||||||
|
#define _CFFI_OP_TYPENAME 21
|
||||||
|
#define _CFFI_OP_CPYTHON_BLTN_V 23 // varargs
|
||||||
|
#define _CFFI_OP_CPYTHON_BLTN_N 25 // noargs
|
||||||
|
#define _CFFI_OP_CPYTHON_BLTN_O 27 // O (i.e. a single arg)
|
||||||
|
#define _CFFI_OP_CONSTANT 29
|
||||||
|
#define _CFFI_OP_CONSTANT_INT 31
|
||||||
|
#define _CFFI_OP_GLOBAL_VAR 33
|
||||||
|
#define _CFFI_OP_DLOPEN_FUNC 35
|
||||||
|
#define _CFFI_OP_DLOPEN_CONST 37
|
||||||
|
#define _CFFI_OP_GLOBAL_VAR_F 39
|
||||||
|
|
||||||
|
#define _CFFI_PRIM_VOID 0
|
||||||
|
#define _CFFI_PRIM_BOOL 1
|
||||||
|
#define _CFFI_PRIM_CHAR 2
|
||||||
|
#define _CFFI_PRIM_SCHAR 3
|
||||||
|
#define _CFFI_PRIM_UCHAR 4
|
||||||
|
#define _CFFI_PRIM_SHORT 5
|
||||||
|
#define _CFFI_PRIM_USHORT 6
|
||||||
|
#define _CFFI_PRIM_INT 7
|
||||||
|
#define _CFFI_PRIM_UINT 8
|
||||||
|
#define _CFFI_PRIM_LONG 9
|
||||||
|
#define _CFFI_PRIM_ULONG 10
|
||||||
|
#define _CFFI_PRIM_LONGLONG 11
|
||||||
|
#define _CFFI_PRIM_ULONGLONG 12
|
||||||
|
#define _CFFI_PRIM_FLOAT 13
|
||||||
|
#define _CFFI_PRIM_DOUBLE 14
|
||||||
|
#define _CFFI_PRIM_LONGDOUBLE 15
|
||||||
|
|
||||||
|
#define _CFFI_PRIM_WCHAR 16
|
||||||
|
#define _CFFI_PRIM_INT8 17
|
||||||
|
#define _CFFI_PRIM_UINT8 18
|
||||||
|
#define _CFFI_PRIM_INT16 19
|
||||||
|
#define _CFFI_PRIM_UINT16 20
|
||||||
|
#define _CFFI_PRIM_INT32 21
|
||||||
|
#define _CFFI_PRIM_UINT32 22
|
||||||
|
#define _CFFI_PRIM_INT64 23
|
||||||
|
#define _CFFI_PRIM_UINT64 24
|
||||||
|
#define _CFFI_PRIM_INTPTR 25
|
||||||
|
#define _CFFI_PRIM_UINTPTR 26
|
||||||
|
#define _CFFI_PRIM_PTRDIFF 27
|
||||||
|
#define _CFFI_PRIM_SIZE 28
|
||||||
|
#define _CFFI_PRIM_SSIZE 29
|
||||||
|
#define _CFFI_PRIM_INT_LEAST8 30
|
||||||
|
#define _CFFI_PRIM_UINT_LEAST8 31
|
||||||
|
#define _CFFI_PRIM_INT_LEAST16 32
|
||||||
|
#define _CFFI_PRIM_UINT_LEAST16 33
|
||||||
|
#define _CFFI_PRIM_INT_LEAST32 34
|
||||||
|
#define _CFFI_PRIM_UINT_LEAST32 35
|
||||||
|
#define _CFFI_PRIM_INT_LEAST64 36
|
||||||
|
#define _CFFI_PRIM_UINT_LEAST64 37
|
||||||
|
#define _CFFI_PRIM_INT_FAST8 38
|
||||||
|
#define _CFFI_PRIM_UINT_FAST8 39
|
||||||
|
#define _CFFI_PRIM_INT_FAST16 40
|
||||||
|
#define _CFFI_PRIM_UINT_FAST16 41
|
||||||
|
#define _CFFI_PRIM_INT_FAST32 42
|
||||||
|
#define _CFFI_PRIM_UINT_FAST32 43
|
||||||
|
#define _CFFI_PRIM_INT_FAST64 44
|
||||||
|
#define _CFFI_PRIM_UINT_FAST64 45
|
||||||
|
#define _CFFI_PRIM_INTMAX 46
|
||||||
|
#define _CFFI_PRIM_UINTMAX 47
|
||||||
|
|
||||||
|
#define _CFFI__NUM_PRIM 48
|
||||||
|
#define _CFFI__UNKNOWN_PRIM (-1)
|
||||||
|
#define _CFFI__UNKNOWN_FLOAT_PRIM (-2)
|
||||||
|
#define _CFFI__UNKNOWN_LONG_DOUBLE (-3)
|
||||||
|
|
||||||
|
|
||||||
|
struct _cffi_global_s {
|
||||||
|
const char *name;
|
||||||
|
void *address;
|
||||||
|
_cffi_opcode_t type_op;
|
||||||
|
void *size_or_direct_fn; // OP_GLOBAL_VAR: size, or 0 if unknown
|
||||||
|
// OP_CPYTHON_BLTN_*: addr of direct function
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _cffi_getconst_s {
|
||||||
|
unsigned long long value;
|
||||||
|
const struct _cffi_type_context_s *ctx;
|
||||||
|
int gindex;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _cffi_struct_union_s {
|
||||||
|
const char *name;
|
||||||
|
int type_index; // -> _cffi_types, on a OP_STRUCT_UNION
|
||||||
|
int flags; // _CFFI_F_* flags below
|
||||||
|
size_t size;
|
||||||
|
int alignment;
|
||||||
|
int first_field_index; // -> _cffi_fields array
|
||||||
|
int num_fields;
|
||||||
|
};
|
||||||
|
#define _CFFI_F_UNION 0x01 // is a union, not a struct
|
||||||
|
#define _CFFI_F_CHECK_FIELDS 0x02 // complain if fields are not in the
|
||||||
|
// "standard layout" or if some are missing
|
||||||
|
#define _CFFI_F_PACKED 0x04 // for CHECK_FIELDS, assume a packed struct
|
||||||
|
#define _CFFI_F_EXTERNAL 0x08 // in some other ffi.include()
|
||||||
|
#define _CFFI_F_OPAQUE 0x10 // opaque
|
||||||
|
|
||||||
|
struct _cffi_field_s {
|
||||||
|
const char *name;
|
||||||
|
size_t field_offset;
|
||||||
|
size_t field_size;
|
||||||
|
_cffi_opcode_t field_type_op;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _cffi_enum_s {
|
||||||
|
const char *name;
|
||||||
|
int type_index; // -> _cffi_types, on a OP_ENUM
|
||||||
|
int type_prim; // _CFFI_PRIM_xxx
|
||||||
|
const char *enumerators; // comma-delimited string
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _cffi_typename_s {
|
||||||
|
const char *name;
|
||||||
|
int type_index; /* if opaque, points to a possibly artificial
|
||||||
|
OP_STRUCT which is itself opaque */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _cffi_type_context_s {
|
||||||
|
_cffi_opcode_t *types;
|
||||||
|
const struct _cffi_global_s *globals;
|
||||||
|
const struct _cffi_field_s *fields;
|
||||||
|
const struct _cffi_struct_union_s *struct_unions;
|
||||||
|
const struct _cffi_enum_s *enums;
|
||||||
|
const struct _cffi_typename_s *typenames;
|
||||||
|
int num_globals;
|
||||||
|
int num_struct_unions;
|
||||||
|
int num_enums;
|
||||||
|
int num_typenames;
|
||||||
|
const char *const *includes;
|
||||||
|
int num_types;
|
||||||
|
int flags; /* future extension */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _cffi_parse_info_s {
|
||||||
|
const struct _cffi_type_context_s *ctx;
|
||||||
|
_cffi_opcode_t *output;
|
||||||
|
unsigned int output_size;
|
||||||
|
size_t error_location;
|
||||||
|
const char *error_message;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef _CFFI_INTERNAL
|
||||||
|
static int parse_c_type(struct _cffi_parse_info_s *info, const char *input);
|
||||||
|
static int search_in_globals(const struct _cffi_type_context_s *ctx,
|
||||||
|
const char *search, size_t search_len);
|
||||||
|
static int search_in_struct_unions(const struct _cffi_type_context_s *ctx,
|
||||||
|
const char *search, size_t search_len);
|
||||||
|
#endif
|
1290
Linux_x86_64/lib/python3.4/site-packages/cffi/recompiler.py
Normal file
1290
Linux_x86_64/lib/python3.4/site-packages/cffi/recompiler.py
Normal file
File diff suppressed because it is too large
Load diff
161
Linux_x86_64/lib/python3.4/site-packages/cffi/setuptools_ext.py
Normal file
161
Linux_x86_64/lib/python3.4/site-packages/cffi/setuptools_ext.py
Normal file
|
@ -0,0 +1,161 @@
|
||||||
|
import os
|
||||||
|
|
||||||
|
try:
|
||||||
|
basestring
|
||||||
|
except NameError:
|
||||||
|
# Python 3.x
|
||||||
|
basestring = str
|
||||||
|
|
||||||
|
def error(msg):
|
||||||
|
from distutils.errors import DistutilsSetupError
|
||||||
|
raise DistutilsSetupError(msg)
|
||||||
|
|
||||||
|
|
||||||
|
def execfile(filename, glob):
|
||||||
|
# We use execfile() (here rewritten for Python 3) instead of
|
||||||
|
# __import__() to load the build script. The problem with
|
||||||
|
# a normal import is that in some packages, the intermediate
|
||||||
|
# __init__.py files may already try to import the file that
|
||||||
|
# we are generating.
|
||||||
|
with open(filename) as f:
|
||||||
|
src = f.read()
|
||||||
|
src += '\n' # Python 2.6 compatibility
|
||||||
|
code = compile(src, filename, 'exec')
|
||||||
|
exec(code, glob, glob)
|
||||||
|
|
||||||
|
|
||||||
|
def add_cffi_module(dist, mod_spec):
|
||||||
|
from cffi.api import FFI
|
||||||
|
|
||||||
|
if not isinstance(mod_spec, basestring):
|
||||||
|
error("argument to 'cffi_modules=...' must be a str or a list of str,"
|
||||||
|
" not %r" % (type(mod_spec).__name__,))
|
||||||
|
mod_spec = str(mod_spec)
|
||||||
|
try:
|
||||||
|
build_file_name, ffi_var_name = mod_spec.split(':')
|
||||||
|
except ValueError:
|
||||||
|
error("%r must be of the form 'path/build.py:ffi_variable'" %
|
||||||
|
(mod_spec,))
|
||||||
|
if not os.path.exists(build_file_name):
|
||||||
|
ext = ''
|
||||||
|
rewritten = build_file_name.replace('.', '/') + '.py'
|
||||||
|
if os.path.exists(rewritten):
|
||||||
|
ext = ' (rewrite cffi_modules to [%r])' % (
|
||||||
|
rewritten + ':' + ffi_var_name,)
|
||||||
|
error("%r does not name an existing file%s" % (build_file_name, ext))
|
||||||
|
|
||||||
|
mod_vars = {'__name__': '__cffi__', '__file__': build_file_name}
|
||||||
|
execfile(build_file_name, mod_vars)
|
||||||
|
|
||||||
|
try:
|
||||||
|
ffi = mod_vars[ffi_var_name]
|
||||||
|
except KeyError:
|
||||||
|
error("%r: object %r not found in module" % (mod_spec,
|
||||||
|
ffi_var_name))
|
||||||
|
if not isinstance(ffi, FFI):
|
||||||
|
ffi = ffi() # maybe it's a function instead of directly an ffi
|
||||||
|
if not isinstance(ffi, FFI):
|
||||||
|
error("%r is not an FFI instance (got %r)" % (mod_spec,
|
||||||
|
type(ffi).__name__))
|
||||||
|
if not hasattr(ffi, '_assigned_source'):
|
||||||
|
error("%r: the set_source() method was not called" % (mod_spec,))
|
||||||
|
module_name, source, source_extension, kwds = ffi._assigned_source
|
||||||
|
if ffi._windows_unicode:
|
||||||
|
kwds = kwds.copy()
|
||||||
|
ffi._apply_windows_unicode(kwds)
|
||||||
|
|
||||||
|
if source is None:
|
||||||
|
_add_py_module(dist, ffi, module_name)
|
||||||
|
else:
|
||||||
|
_add_c_module(dist, ffi, module_name, source, source_extension, kwds)
|
||||||
|
|
||||||
|
|
||||||
|
def _add_c_module(dist, ffi, module_name, source, source_extension, kwds):
|
||||||
|
from distutils.core import Extension
|
||||||
|
from distutils.command.build_ext import build_ext
|
||||||
|
from distutils.dir_util import mkpath
|
||||||
|
from distutils import log
|
||||||
|
from cffi import recompiler
|
||||||
|
|
||||||
|
allsources = ['$PLACEHOLDER']
|
||||||
|
allsources.extend(kwds.pop('sources', []))
|
||||||
|
ext = Extension(name=module_name, sources=allsources, **kwds)
|
||||||
|
|
||||||
|
def make_mod(tmpdir, pre_run=None):
|
||||||
|
c_file = os.path.join(tmpdir, module_name + source_extension)
|
||||||
|
log.info("generating cffi module %r" % c_file)
|
||||||
|
mkpath(tmpdir)
|
||||||
|
# a setuptools-only, API-only hook: called with the "ext" and "ffi"
|
||||||
|
# arguments just before we turn the ffi into C code. To use it,
|
||||||
|
# subclass the 'distutils.command.build_ext.build_ext' class and
|
||||||
|
# add a method 'def pre_run(self, ext, ffi)'.
|
||||||
|
if pre_run is not None:
|
||||||
|
pre_run(ext, ffi)
|
||||||
|
updated = recompiler.make_c_source(ffi, module_name, source, c_file)
|
||||||
|
if not updated:
|
||||||
|
log.info("already up-to-date")
|
||||||
|
return c_file
|
||||||
|
|
||||||
|
if dist.ext_modules is None:
|
||||||
|
dist.ext_modules = []
|
||||||
|
dist.ext_modules.append(ext)
|
||||||
|
|
||||||
|
base_class = dist.cmdclass.get('build_ext', build_ext)
|
||||||
|
class build_ext_make_mod(base_class):
|
||||||
|
def run(self):
|
||||||
|
if ext.sources[0] == '$PLACEHOLDER':
|
||||||
|
pre_run = getattr(self, 'pre_run', None)
|
||||||
|
ext.sources[0] = make_mod(self.build_temp, pre_run)
|
||||||
|
base_class.run(self)
|
||||||
|
dist.cmdclass['build_ext'] = build_ext_make_mod
|
||||||
|
# NB. multiple runs here will create multiple 'build_ext_make_mod'
|
||||||
|
# classes. Even in this case the 'build_ext' command should be
|
||||||
|
# run once; but just in case, the logic above does nothing if
|
||||||
|
# called again.
|
||||||
|
|
||||||
|
|
||||||
|
def _add_py_module(dist, ffi, module_name):
|
||||||
|
from distutils.dir_util import mkpath
|
||||||
|
from distutils.command.build_py import build_py
|
||||||
|
from distutils.command.build_ext import build_ext
|
||||||
|
from distutils import log
|
||||||
|
from cffi import recompiler
|
||||||
|
|
||||||
|
def generate_mod(py_file):
|
||||||
|
log.info("generating cffi module %r" % py_file)
|
||||||
|
mkpath(os.path.dirname(py_file))
|
||||||
|
updated = recompiler.make_py_source(ffi, module_name, py_file)
|
||||||
|
if not updated:
|
||||||
|
log.info("already up-to-date")
|
||||||
|
|
||||||
|
base_class = dist.cmdclass.get('build_py', build_py)
|
||||||
|
class build_py_make_mod(base_class):
|
||||||
|
def run(self):
|
||||||
|
base_class.run(self)
|
||||||
|
module_path = module_name.split('.')
|
||||||
|
module_path[-1] += '.py'
|
||||||
|
generate_mod(os.path.join(self.build_lib, *module_path))
|
||||||
|
dist.cmdclass['build_py'] = build_py_make_mod
|
||||||
|
|
||||||
|
# the following is only for "build_ext -i"
|
||||||
|
base_class_2 = dist.cmdclass.get('build_ext', build_ext)
|
||||||
|
class build_ext_make_mod(base_class_2):
|
||||||
|
def run(self):
|
||||||
|
base_class_2.run(self)
|
||||||
|
if self.inplace:
|
||||||
|
# from get_ext_fullpath() in distutils/command/build_ext.py
|
||||||
|
module_path = module_name.split('.')
|
||||||
|
package = '.'.join(module_path[:-1])
|
||||||
|
build_py = self.get_finalized_command('build_py')
|
||||||
|
package_dir = build_py.get_package_dir(package)
|
||||||
|
file_name = module_path[-1] + '.py'
|
||||||
|
generate_mod(os.path.join(package_dir, file_name))
|
||||||
|
dist.cmdclass['build_ext'] = build_ext_make_mod
|
||||||
|
|
||||||
|
def cffi_modules(dist, attr, value):
|
||||||
|
assert attr == 'cffi_modules'
|
||||||
|
if isinstance(value, basestring):
|
||||||
|
value = [value]
|
||||||
|
|
||||||
|
for cffi_module in value:
|
||||||
|
add_cffi_module(dist, cffi_module)
|
|
@ -65,7 +65,7 @@ class VCPythonEngine(object):
|
||||||
# The following two 'chained_list_constants' items contains
|
# The following two 'chained_list_constants' items contains
|
||||||
# the head of these two chained lists, as a string that gives the
|
# the head of these two chained lists, as a string that gives the
|
||||||
# call to do, if any.
|
# call to do, if any.
|
||||||
self._chained_list_constants = ['0', '0']
|
self._chained_list_constants = ['((void)lib,0)', '((void)lib,0)']
|
||||||
#
|
#
|
||||||
prnt = self._prnt
|
prnt = self._prnt
|
||||||
# first paste some standard set of lines that are mostly '#define'
|
# first paste some standard set of lines that are mostly '#define'
|
||||||
|
@ -138,15 +138,26 @@ class VCPythonEngine(object):
|
||||||
prnt()
|
prnt()
|
||||||
prnt('#endif')
|
prnt('#endif')
|
||||||
|
|
||||||
def load_library(self):
|
def load_library(self, flags=None):
|
||||||
# XXX review all usages of 'self' here!
|
# XXX review all usages of 'self' here!
|
||||||
# import it as a new extension module
|
# import it as a new extension module
|
||||||
|
imp.acquire_lock()
|
||||||
try:
|
try:
|
||||||
|
if hasattr(sys, "getdlopenflags"):
|
||||||
|
previous_flags = sys.getdlopenflags()
|
||||||
|
try:
|
||||||
|
if hasattr(sys, "setdlopenflags") and flags is not None:
|
||||||
|
sys.setdlopenflags(flags)
|
||||||
module = imp.load_dynamic(self.verifier.get_module_name(),
|
module = imp.load_dynamic(self.verifier.get_module_name(),
|
||||||
self.verifier.modulefilename)
|
self.verifier.modulefilename)
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
error = "importing %r: %s" % (self.verifier.modulefilename, e)
|
error = "importing %r: %s" % (self.verifier.modulefilename, e)
|
||||||
raise ffiplatform.VerificationError(error)
|
raise ffiplatform.VerificationError(error)
|
||||||
|
finally:
|
||||||
|
if hasattr(sys, "setdlopenflags"):
|
||||||
|
sys.setdlopenflags(previous_flags)
|
||||||
|
finally:
|
||||||
|
imp.release_lock()
|
||||||
#
|
#
|
||||||
# call loading_cpy_struct() to get the struct layout inferred by
|
# call loading_cpy_struct() to get the struct layout inferred by
|
||||||
# the C compiler
|
# the C compiler
|
||||||
|
@ -186,7 +197,10 @@ class VCPythonEngine(object):
|
||||||
return library
|
return library
|
||||||
|
|
||||||
def _get_declarations(self):
|
def _get_declarations(self):
|
||||||
return sorted(self.ffi._parser._declarations.items())
|
lst = [(key, tp) for (key, (tp, qual)) in
|
||||||
|
self.ffi._parser._declarations.items()]
|
||||||
|
lst.sort()
|
||||||
|
return lst
|
||||||
|
|
||||||
def _generate(self, step_name):
|
def _generate(self, step_name):
|
||||||
for name, tp in self._get_declarations():
|
for name, tp in self._get_declarations():
|
||||||
|
@ -228,7 +242,8 @@ class VCPythonEngine(object):
|
||||||
converter = '_cffi_to_c_int'
|
converter = '_cffi_to_c_int'
|
||||||
extraarg = ', %s' % tp.name
|
extraarg = ', %s' % tp.name
|
||||||
else:
|
else:
|
||||||
converter = '_cffi_to_c_%s' % (tp.name.replace(' ', '_'),)
|
converter = '(%s)_cffi_to_c_%s' % (tp.get_c_name(''),
|
||||||
|
tp.name.replace(' ', '_'))
|
||||||
errvalue = '-1'
|
errvalue = '-1'
|
||||||
#
|
#
|
||||||
elif isinstance(tp, model.PointerType):
|
elif isinstance(tp, model.PointerType):
|
||||||
|
@ -267,8 +282,8 @@ class VCPythonEngine(object):
|
||||||
self._prnt(' if (datasize != 0) {')
|
self._prnt(' if (datasize != 0) {')
|
||||||
self._prnt(' if (datasize < 0)')
|
self._prnt(' if (datasize < 0)')
|
||||||
self._prnt(' %s;' % errcode)
|
self._prnt(' %s;' % errcode)
|
||||||
self._prnt(' %s = alloca(datasize);' % (tovar,))
|
self._prnt(' %s = alloca((size_t)datasize);' % (tovar,))
|
||||||
self._prnt(' memset((void *)%s, 0, datasize);' % (tovar,))
|
self._prnt(' memset((void *)%s, 0, (size_t)datasize);' % (tovar,))
|
||||||
self._prnt(' if (_cffi_convert_array_from_object('
|
self._prnt(' if (_cffi_convert_array_from_object('
|
||||||
'(char *)%s, _cffi_type(%d), %s) < 0)' % (
|
'(char *)%s, _cffi_type(%d), %s) < 0)' % (
|
||||||
tovar, self._gettypenum(tp), fromvar))
|
tovar, self._gettypenum(tp), fromvar))
|
||||||
|
@ -336,7 +351,7 @@ class VCPythonEngine(object):
|
||||||
prnt = self._prnt
|
prnt = self._prnt
|
||||||
numargs = len(tp.args)
|
numargs = len(tp.args)
|
||||||
if numargs == 0:
|
if numargs == 0:
|
||||||
argname = 'no_arg'
|
argname = 'noarg'
|
||||||
elif numargs == 1:
|
elif numargs == 1:
|
||||||
argname = 'arg0'
|
argname = 'arg0'
|
||||||
else:
|
else:
|
||||||
|
@ -386,6 +401,9 @@ class VCPythonEngine(object):
|
||||||
prnt(' Py_END_ALLOW_THREADS')
|
prnt(' Py_END_ALLOW_THREADS')
|
||||||
prnt()
|
prnt()
|
||||||
#
|
#
|
||||||
|
prnt(' (void)self; /* unused */')
|
||||||
|
if numargs == 0:
|
||||||
|
prnt(' (void)noarg; /* unused */')
|
||||||
if result_code:
|
if result_code:
|
||||||
prnt(' return %s;' %
|
prnt(' return %s;' %
|
||||||
self._convert_expr_from_c(tp.result, 'result', 'result type'))
|
self._convert_expr_from_c(tp.result, 'result', 'result type'))
|
||||||
|
@ -452,7 +470,8 @@ class VCPythonEngine(object):
|
||||||
prnt('static void %s(%s *p)' % (checkfuncname, cname))
|
prnt('static void %s(%s *p)' % (checkfuncname, cname))
|
||||||
prnt('{')
|
prnt('{')
|
||||||
prnt(' /* only to generate compile-time warnings or errors */')
|
prnt(' /* only to generate compile-time warnings or errors */')
|
||||||
for fname, ftype, fbitsize in tp.enumfields():
|
prnt(' (void)p;')
|
||||||
|
for fname, ftype, fbitsize, fqual in tp.enumfields():
|
||||||
if (isinstance(ftype, model.PrimitiveType)
|
if (isinstance(ftype, model.PrimitiveType)
|
||||||
and ftype.is_integer_type()) or fbitsize >= 0:
|
and ftype.is_integer_type()) or fbitsize >= 0:
|
||||||
# accept all integers, but complain on float or double
|
# accept all integers, but complain on float or double
|
||||||
|
@ -461,7 +480,8 @@ class VCPythonEngine(object):
|
||||||
# only accept exactly the type declared.
|
# only accept exactly the type declared.
|
||||||
try:
|
try:
|
||||||
prnt(' { %s = &p->%s; (void)tmp; }' % (
|
prnt(' { %s = &p->%s; (void)tmp; }' % (
|
||||||
ftype.get_c_name('*tmp', 'field %r'%fname), fname))
|
ftype.get_c_name('*tmp', 'field %r'%fname, quals=fqual),
|
||||||
|
fname))
|
||||||
except ffiplatform.VerificationError as e:
|
except ffiplatform.VerificationError as e:
|
||||||
prnt(' /* %s */' % str(e)) # cannot verify it, ignore
|
prnt(' /* %s */' % str(e)) # cannot verify it, ignore
|
||||||
prnt('}')
|
prnt('}')
|
||||||
|
@ -472,7 +492,7 @@ class VCPythonEngine(object):
|
||||||
prnt(' static Py_ssize_t nums[] = {')
|
prnt(' static Py_ssize_t nums[] = {')
|
||||||
prnt(' sizeof(%s),' % cname)
|
prnt(' sizeof(%s),' % cname)
|
||||||
prnt(' offsetof(struct _cffi_aligncheck, y),')
|
prnt(' offsetof(struct _cffi_aligncheck, y),')
|
||||||
for fname, ftype, fbitsize in tp.enumfields():
|
for fname, ftype, fbitsize, fqual in tp.enumfields():
|
||||||
if fbitsize >= 0:
|
if fbitsize >= 0:
|
||||||
continue # xxx ignore fbitsize for now
|
continue # xxx ignore fbitsize for now
|
||||||
prnt(' offsetof(%s, %s),' % (cname, fname))
|
prnt(' offsetof(%s, %s),' % (cname, fname))
|
||||||
|
@ -482,6 +502,8 @@ class VCPythonEngine(object):
|
||||||
prnt(' sizeof(((%s *)0)->%s),' % (cname, fname))
|
prnt(' sizeof(((%s *)0)->%s),' % (cname, fname))
|
||||||
prnt(' -1')
|
prnt(' -1')
|
||||||
prnt(' };')
|
prnt(' };')
|
||||||
|
prnt(' (void)self; /* unused */')
|
||||||
|
prnt(' (void)noarg; /* unused */')
|
||||||
prnt(' return _cffi_get_struct_layout(nums);')
|
prnt(' return _cffi_get_struct_layout(nums);')
|
||||||
prnt(' /* the next line is not executed, but compiled */')
|
prnt(' /* the next line is not executed, but compiled */')
|
||||||
prnt(' %s(0);' % (checkfuncname,))
|
prnt(' %s(0);' % (checkfuncname,))
|
||||||
|
@ -534,7 +556,7 @@ class VCPythonEngine(object):
|
||||||
check(layout[0], ffi.sizeof(BStruct), "wrong total size")
|
check(layout[0], ffi.sizeof(BStruct), "wrong total size")
|
||||||
check(layout[1], ffi.alignof(BStruct), "wrong total alignment")
|
check(layout[1], ffi.alignof(BStruct), "wrong total alignment")
|
||||||
i = 2
|
i = 2
|
||||||
for fname, ftype, fbitsize in tp.enumfields():
|
for fname, ftype, fbitsize, fqual in tp.enumfields():
|
||||||
if fbitsize >= 0:
|
if fbitsize >= 0:
|
||||||
continue # xxx ignore fbitsize for now
|
continue # xxx ignore fbitsize for now
|
||||||
check(layout[i], ffi.offsetof(BStruct, fname),
|
check(layout[i], ffi.offsetof(BStruct, fname),
|
||||||
|
@ -578,7 +600,8 @@ class VCPythonEngine(object):
|
||||||
# constants, likely declared with '#define'
|
# constants, likely declared with '#define'
|
||||||
|
|
||||||
def _generate_cpy_const(self, is_int, name, tp=None, category='const',
|
def _generate_cpy_const(self, is_int, name, tp=None, category='const',
|
||||||
vartp=None, delayed=True, size_too=False):
|
vartp=None, delayed=True, size_too=False,
|
||||||
|
check_value=None):
|
||||||
prnt = self._prnt
|
prnt = self._prnt
|
||||||
funcname = '_cffi_%s_%s' % (category, name)
|
funcname = '_cffi_%s_%s' % (category, name)
|
||||||
prnt('static int %s(PyObject *lib)' % funcname)
|
prnt('static int %s(PyObject *lib)' % funcname)
|
||||||
|
@ -590,6 +613,9 @@ class VCPythonEngine(object):
|
||||||
else:
|
else:
|
||||||
assert category == 'const'
|
assert category == 'const'
|
||||||
#
|
#
|
||||||
|
if check_value is not None:
|
||||||
|
self._check_int_constant_value(name, check_value)
|
||||||
|
#
|
||||||
if not is_int:
|
if not is_int:
|
||||||
if category == 'var':
|
if category == 'var':
|
||||||
realexpr = '&' + name
|
realexpr = '&' + name
|
||||||
|
@ -637,6 +663,27 @@ class VCPythonEngine(object):
|
||||||
# ----------
|
# ----------
|
||||||
# enums
|
# enums
|
||||||
|
|
||||||
|
def _check_int_constant_value(self, name, value, err_prefix=''):
|
||||||
|
prnt = self._prnt
|
||||||
|
if value <= 0:
|
||||||
|
prnt(' if ((%s) > 0 || (long)(%s) != %dL) {' % (
|
||||||
|
name, name, value))
|
||||||
|
else:
|
||||||
|
prnt(' if ((%s) <= 0 || (unsigned long)(%s) != %dUL) {' % (
|
||||||
|
name, name, value))
|
||||||
|
prnt(' char buf[64];')
|
||||||
|
prnt(' if ((%s) <= 0)' % name)
|
||||||
|
prnt(' snprintf(buf, 63, "%%ld", (long)(%s));' % name)
|
||||||
|
prnt(' else')
|
||||||
|
prnt(' snprintf(buf, 63, "%%lu", (unsigned long)(%s));' %
|
||||||
|
name)
|
||||||
|
prnt(' PyErr_Format(_cffi_VerificationError,')
|
||||||
|
prnt(' "%s%s has the real value %s, not %s",')
|
||||||
|
prnt(' "%s", "%s", buf, "%d");' % (
|
||||||
|
err_prefix, name, value))
|
||||||
|
prnt(' return -1;')
|
||||||
|
prnt(' }')
|
||||||
|
|
||||||
def _enum_funcname(self, prefix, name):
|
def _enum_funcname(self, prefix, name):
|
||||||
# "$enum_$1" => "___D_enum____D_1"
|
# "$enum_$1" => "___D_enum____D_1"
|
||||||
name = name.replace('$', '___D_')
|
name = name.replace('$', '___D_')
|
||||||
|
@ -653,25 +700,8 @@ class VCPythonEngine(object):
|
||||||
prnt('static int %s(PyObject *lib)' % funcname)
|
prnt('static int %s(PyObject *lib)' % funcname)
|
||||||
prnt('{')
|
prnt('{')
|
||||||
for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues):
|
for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues):
|
||||||
if enumvalue < 0:
|
self._check_int_constant_value(enumerator, enumvalue,
|
||||||
prnt(' if ((%s) >= 0 || (long)(%s) != %dL) {' % (
|
"enum %s: " % name)
|
||||||
enumerator, enumerator, enumvalue))
|
|
||||||
else:
|
|
||||||
prnt(' if ((%s) < 0 || (unsigned long)(%s) != %dUL) {' % (
|
|
||||||
enumerator, enumerator, enumvalue))
|
|
||||||
prnt(' char buf[64];')
|
|
||||||
prnt(' if ((%s) < 0)' % enumerator)
|
|
||||||
prnt(' snprintf(buf, 63, "%%ld", (long)(%s));' % enumerator)
|
|
||||||
prnt(' else')
|
|
||||||
prnt(' snprintf(buf, 63, "%%lu", (unsigned long)(%s));' %
|
|
||||||
enumerator)
|
|
||||||
prnt(' PyErr_Format(_cffi_VerificationError,')
|
|
||||||
prnt(' "enum %s: %s has the real value %s, '
|
|
||||||
'not %s",')
|
|
||||||
prnt(' "%s", "%s", buf, "%d");' % (
|
|
||||||
name, enumerator, enumvalue))
|
|
||||||
prnt(' return -1;')
|
|
||||||
prnt(' }')
|
|
||||||
prnt(' return %s;' % self._chained_list_constants[True])
|
prnt(' return %s;' % self._chained_list_constants[True])
|
||||||
self._chained_list_constants[True] = funcname + '(lib)'
|
self._chained_list_constants[True] = funcname + '(lib)'
|
||||||
prnt('}')
|
prnt('}')
|
||||||
|
@ -695,8 +725,11 @@ class VCPythonEngine(object):
|
||||||
# macros: for now only for integers
|
# macros: for now only for integers
|
||||||
|
|
||||||
def _generate_cpy_macro_decl(self, tp, name):
|
def _generate_cpy_macro_decl(self, tp, name):
|
||||||
assert tp == '...'
|
if tp == '...':
|
||||||
self._generate_cpy_const(True, name)
|
check_value = None
|
||||||
|
else:
|
||||||
|
check_value = tp # an integer
|
||||||
|
self._generate_cpy_const(True, name, check_value=check_value)
|
||||||
|
|
||||||
_generate_cpy_macro_collecttype = _generate_nothing
|
_generate_cpy_macro_collecttype = _generate_nothing
|
||||||
_generate_cpy_macro_method = _generate_nothing
|
_generate_cpy_macro_method = _generate_nothing
|
||||||
|
@ -783,6 +816,24 @@ cffimod_header = r'''
|
||||||
typedef unsigned __int16 uint16_t;
|
typedef unsigned __int16 uint16_t;
|
||||||
typedef unsigned __int32 uint32_t;
|
typedef unsigned __int32 uint32_t;
|
||||||
typedef unsigned __int64 uint64_t;
|
typedef unsigned __int64 uint64_t;
|
||||||
|
typedef __int8 int_least8_t;
|
||||||
|
typedef __int16 int_least16_t;
|
||||||
|
typedef __int32 int_least32_t;
|
||||||
|
typedef __int64 int_least64_t;
|
||||||
|
typedef unsigned __int8 uint_least8_t;
|
||||||
|
typedef unsigned __int16 uint_least16_t;
|
||||||
|
typedef unsigned __int32 uint_least32_t;
|
||||||
|
typedef unsigned __int64 uint_least64_t;
|
||||||
|
typedef __int8 int_fast8_t;
|
||||||
|
typedef __int16 int_fast16_t;
|
||||||
|
typedef __int32 int_fast32_t;
|
||||||
|
typedef __int64 int_fast64_t;
|
||||||
|
typedef unsigned __int8 uint_fast8_t;
|
||||||
|
typedef unsigned __int16 uint_fast16_t;
|
||||||
|
typedef unsigned __int32 uint_fast32_t;
|
||||||
|
typedef unsigned __int64 uint_fast64_t;
|
||||||
|
typedef __int64 intmax_t;
|
||||||
|
typedef unsigned __int64 uintmax_t;
|
||||||
# else
|
# else
|
||||||
# include <stdint.h>
|
# include <stdint.h>
|
||||||
# endif
|
# endif
|
||||||
|
@ -829,14 +880,18 @@ cffimod_header = r'''
|
||||||
|
|
||||||
#define _cffi_from_c_int(x, type) \
|
#define _cffi_from_c_int(x, type) \
|
||||||
(((type)-1) > 0 ? /* unsigned */ \
|
(((type)-1) > 0 ? /* unsigned */ \
|
||||||
(sizeof(type) < sizeof(long) ? PyInt_FromLong(x) : \
|
(sizeof(type) < sizeof(long) ? \
|
||||||
sizeof(type) == sizeof(long) ? PyLong_FromUnsignedLong(x) : \
|
PyInt_FromLong((long)x) : \
|
||||||
PyLong_FromUnsignedLongLong(x)) \
|
sizeof(type) == sizeof(long) ? \
|
||||||
: (sizeof(type) <= sizeof(long) ? PyInt_FromLong(x) : \
|
PyLong_FromUnsignedLong((unsigned long)x) : \
|
||||||
PyLong_FromLongLong(x)))
|
PyLong_FromUnsignedLongLong((unsigned long long)x)) : \
|
||||||
|
(sizeof(type) <= sizeof(long) ? \
|
||||||
|
PyInt_FromLong((long)x) : \
|
||||||
|
PyLong_FromLongLong((long long)x)))
|
||||||
|
|
||||||
#define _cffi_to_c_int(o, type) \
|
#define _cffi_to_c_int(o, type) \
|
||||||
(sizeof(type) == 1 ? (((type)-1) > 0 ? (type)_cffi_to_c_u8(o) \
|
((type)( \
|
||||||
|
sizeof(type) == 1 ? (((type)-1) > 0 ? (type)_cffi_to_c_u8(o) \
|
||||||
: (type)_cffi_to_c_i8(o)) : \
|
: (type)_cffi_to_c_i8(o)) : \
|
||||||
sizeof(type) == 2 ? (((type)-1) > 0 ? (type)_cffi_to_c_u16(o) \
|
sizeof(type) == 2 ? (((type)-1) > 0 ? (type)_cffi_to_c_u16(o) \
|
||||||
: (type)_cffi_to_c_i16(o)) : \
|
: (type)_cffi_to_c_i16(o)) : \
|
||||||
|
@ -844,7 +899,7 @@ cffimod_header = r'''
|
||||||
: (type)_cffi_to_c_i32(o)) : \
|
: (type)_cffi_to_c_i32(o)) : \
|
||||||
sizeof(type) == 8 ? (((type)-1) > 0 ? (type)_cffi_to_c_u64(o) \
|
sizeof(type) == 8 ? (((type)-1) > 0 ? (type)_cffi_to_c_u64(o) \
|
||||||
: (type)_cffi_to_c_i64(o)) : \
|
: (type)_cffi_to_c_i64(o)) : \
|
||||||
(Py_FatalError("unsupported size for type " #type), 0))
|
(Py_FatalError("unsupported size for type " #type), (type)0)))
|
||||||
|
|
||||||
#define _cffi_to_c_i8 \
|
#define _cffi_to_c_i8 \
|
||||||
((int(*)(PyObject *))_cffi_exports[1])
|
((int(*)(PyObject *))_cffi_exports[1])
|
||||||
|
@ -907,6 +962,7 @@ static PyObject *_cffi_setup(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
PyObject *library;
|
PyObject *library;
|
||||||
int was_alive = (_cffi_types != NULL);
|
int was_alive = (_cffi_types != NULL);
|
||||||
|
(void)self; /* unused */
|
||||||
if (!PyArg_ParseTuple(args, "OOO", &_cffi_types, &_cffi_VerificationError,
|
if (!PyArg_ParseTuple(args, "OOO", &_cffi_types, &_cffi_VerificationError,
|
||||||
&library))
|
&library))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -58,12 +58,12 @@ class VGenericEngine(object):
|
||||||
modname = self.verifier.get_module_name()
|
modname = self.verifier.get_module_name()
|
||||||
prnt("void %s%s(void) { }\n" % (prefix, modname))
|
prnt("void %s%s(void) { }\n" % (prefix, modname))
|
||||||
|
|
||||||
def load_library(self):
|
def load_library(self, flags=0):
|
||||||
# import it with the CFFI backend
|
# import it with the CFFI backend
|
||||||
backend = self.ffi._backend
|
backend = self.ffi._backend
|
||||||
# needs to make a path that contains '/', on Posix
|
# needs to make a path that contains '/', on Posix
|
||||||
filename = os.path.join(os.curdir, self.verifier.modulefilename)
|
filename = os.path.join(os.curdir, self.verifier.modulefilename)
|
||||||
module = backend.load_library(filename)
|
module = backend.load_library(filename, flags)
|
||||||
#
|
#
|
||||||
# call loading_gen_struct() to get the struct layout inferred by
|
# call loading_gen_struct() to get the struct layout inferred by
|
||||||
# the C compiler
|
# the C compiler
|
||||||
|
@ -87,7 +87,10 @@ class VGenericEngine(object):
|
||||||
return library
|
return library
|
||||||
|
|
||||||
def _get_declarations(self):
|
def _get_declarations(self):
|
||||||
return sorted(self.ffi._parser._declarations.items())
|
lst = [(key, tp) for (key, (tp, qual)) in
|
||||||
|
self.ffi._parser._declarations.items()]
|
||||||
|
lst.sort()
|
||||||
|
return lst
|
||||||
|
|
||||||
def _generate(self, step_name):
|
def _generate(self, step_name):
|
||||||
for name, tp in self._get_declarations():
|
for name, tp in self._get_declarations():
|
||||||
|
@ -149,15 +152,25 @@ class VGenericEngine(object):
|
||||||
context = 'argument of %s' % name
|
context = 'argument of %s' % name
|
||||||
arglist = [type.get_c_name(' %s' % arg, context)
|
arglist = [type.get_c_name(' %s' % arg, context)
|
||||||
for type, arg in zip(tp.args, argnames)]
|
for type, arg in zip(tp.args, argnames)]
|
||||||
|
tpresult = tp.result
|
||||||
|
if isinstance(tpresult, model.StructOrUnion):
|
||||||
|
arglist.insert(0, tpresult.get_c_name(' *r', context))
|
||||||
|
tpresult = model.void_type
|
||||||
arglist = ', '.join(arglist) or 'void'
|
arglist = ', '.join(arglist) or 'void'
|
||||||
wrappername = '_cffi_f_%s' % name
|
wrappername = '_cffi_f_%s' % name
|
||||||
self.export_symbols.append(wrappername)
|
self.export_symbols.append(wrappername)
|
||||||
funcdecl = ' %s(%s)' % (wrappername, arglist)
|
if tp.abi:
|
||||||
|
abi = tp.abi + ' '
|
||||||
|
else:
|
||||||
|
abi = ''
|
||||||
|
funcdecl = ' %s%s(%s)' % (abi, wrappername, arglist)
|
||||||
context = 'result of %s' % name
|
context = 'result of %s' % name
|
||||||
prnt(tp.result.get_c_name(funcdecl, context))
|
prnt(tpresult.get_c_name(funcdecl, context))
|
||||||
prnt('{')
|
prnt('{')
|
||||||
#
|
#
|
||||||
if not isinstance(tp.result, model.VoidType):
|
if isinstance(tp.result, model.StructOrUnion):
|
||||||
|
result_code = '*r = '
|
||||||
|
elif not isinstance(tp.result, model.VoidType):
|
||||||
result_code = 'return '
|
result_code = 'return '
|
||||||
else:
|
else:
|
||||||
result_code = ''
|
result_code = ''
|
||||||
|
@ -174,15 +187,26 @@ class VGenericEngine(object):
|
||||||
else:
|
else:
|
||||||
indirections = []
|
indirections = []
|
||||||
base_tp = tp
|
base_tp = tp
|
||||||
if any(isinstance(typ, model.StructOrUnion) for typ in tp.args):
|
if (any(isinstance(typ, model.StructOrUnion) for typ in tp.args)
|
||||||
|
or isinstance(tp.result, model.StructOrUnion)):
|
||||||
indirect_args = []
|
indirect_args = []
|
||||||
for i, typ in enumerate(tp.args):
|
for i, typ in enumerate(tp.args):
|
||||||
if isinstance(typ, model.StructOrUnion):
|
if isinstance(typ, model.StructOrUnion):
|
||||||
typ = model.PointerType(typ)
|
typ = model.PointerType(typ)
|
||||||
indirections.append((i, typ))
|
indirections.append((i, typ))
|
||||||
indirect_args.append(typ)
|
indirect_args.append(typ)
|
||||||
|
indirect_result = tp.result
|
||||||
|
if isinstance(indirect_result, model.StructOrUnion):
|
||||||
|
if indirect_result.fldtypes is None:
|
||||||
|
raise TypeError("'%s' is used as result type, "
|
||||||
|
"but is opaque" % (
|
||||||
|
indirect_result._get_c_name(),))
|
||||||
|
indirect_result = model.PointerType(indirect_result)
|
||||||
|
indirect_args.insert(0, indirect_result)
|
||||||
|
indirections.insert(0, ("result", indirect_result))
|
||||||
|
indirect_result = model.void_type
|
||||||
tp = model.FunctionPtrType(tuple(indirect_args),
|
tp = model.FunctionPtrType(tuple(indirect_args),
|
||||||
tp.result, tp.ellipsis)
|
indirect_result, tp.ellipsis)
|
||||||
BFunc = self.ffi._get_cached_btype(tp)
|
BFunc = self.ffi._get_cached_btype(tp)
|
||||||
wrappername = '_cffi_f_%s' % name
|
wrappername = '_cffi_f_%s' % name
|
||||||
newfunction = module.load_function(BFunc, wrappername)
|
newfunction = module.load_function(BFunc, wrappername)
|
||||||
|
@ -195,6 +219,13 @@ class VGenericEngine(object):
|
||||||
def _make_struct_wrapper(self, oldfunc, i, tp, base_tp):
|
def _make_struct_wrapper(self, oldfunc, i, tp, base_tp):
|
||||||
backend = self.ffi._backend
|
backend = self.ffi._backend
|
||||||
BType = self.ffi._get_cached_btype(tp)
|
BType = self.ffi._get_cached_btype(tp)
|
||||||
|
if i == "result":
|
||||||
|
ffi = self.ffi
|
||||||
|
def newfunc(*args):
|
||||||
|
res = ffi.new(BType)
|
||||||
|
oldfunc(res, *args)
|
||||||
|
return res[0]
|
||||||
|
else:
|
||||||
def newfunc(*args):
|
def newfunc(*args):
|
||||||
args = args[:i] + (backend.newp(BType, args[i]),) + args[i+1:]
|
args = args[:i] + (backend.newp(BType, args[i]),) + args[i+1:]
|
||||||
return oldfunc(*args)
|
return oldfunc(*args)
|
||||||
|
@ -235,7 +266,8 @@ class VGenericEngine(object):
|
||||||
prnt('static void %s(%s *p)' % (checkfuncname, cname))
|
prnt('static void %s(%s *p)' % (checkfuncname, cname))
|
||||||
prnt('{')
|
prnt('{')
|
||||||
prnt(' /* only to generate compile-time warnings or errors */')
|
prnt(' /* only to generate compile-time warnings or errors */')
|
||||||
for fname, ftype, fbitsize in tp.enumfields():
|
prnt(' (void)p;')
|
||||||
|
for fname, ftype, fbitsize, fqual in tp.enumfields():
|
||||||
if (isinstance(ftype, model.PrimitiveType)
|
if (isinstance(ftype, model.PrimitiveType)
|
||||||
and ftype.is_integer_type()) or fbitsize >= 0:
|
and ftype.is_integer_type()) or fbitsize >= 0:
|
||||||
# accept all integers, but complain on float or double
|
# accept all integers, but complain on float or double
|
||||||
|
@ -244,7 +276,8 @@ class VGenericEngine(object):
|
||||||
# only accept exactly the type declared.
|
# only accept exactly the type declared.
|
||||||
try:
|
try:
|
||||||
prnt(' { %s = &p->%s; (void)tmp; }' % (
|
prnt(' { %s = &p->%s; (void)tmp; }' % (
|
||||||
ftype.get_c_name('*tmp', 'field %r'%fname), fname))
|
ftype.get_c_name('*tmp', 'field %r'%fname, quals=fqual),
|
||||||
|
fname))
|
||||||
except ffiplatform.VerificationError as e:
|
except ffiplatform.VerificationError as e:
|
||||||
prnt(' /* %s */' % str(e)) # cannot verify it, ignore
|
prnt(' /* %s */' % str(e)) # cannot verify it, ignore
|
||||||
prnt('}')
|
prnt('}')
|
||||||
|
@ -255,7 +288,7 @@ class VGenericEngine(object):
|
||||||
prnt(' static intptr_t nums[] = {')
|
prnt(' static intptr_t nums[] = {')
|
||||||
prnt(' sizeof(%s),' % cname)
|
prnt(' sizeof(%s),' % cname)
|
||||||
prnt(' offsetof(struct _cffi_aligncheck, y),')
|
prnt(' offsetof(struct _cffi_aligncheck, y),')
|
||||||
for fname, ftype, fbitsize in tp.enumfields():
|
for fname, ftype, fbitsize, fqual in tp.enumfields():
|
||||||
if fbitsize >= 0:
|
if fbitsize >= 0:
|
||||||
continue # xxx ignore fbitsize for now
|
continue # xxx ignore fbitsize for now
|
||||||
prnt(' offsetof(%s, %s),' % (cname, fname))
|
prnt(' offsetof(%s, %s),' % (cname, fname))
|
||||||
|
@ -317,7 +350,7 @@ class VGenericEngine(object):
|
||||||
check(layout[0], ffi.sizeof(BStruct), "wrong total size")
|
check(layout[0], ffi.sizeof(BStruct), "wrong total size")
|
||||||
check(layout[1], ffi.alignof(BStruct), "wrong total alignment")
|
check(layout[1], ffi.alignof(BStruct), "wrong total alignment")
|
||||||
i = 2
|
i = 2
|
||||||
for fname, ftype, fbitsize in tp.enumfields():
|
for fname, ftype, fbitsize, fqual in tp.enumfields():
|
||||||
if fbitsize >= 0:
|
if fbitsize >= 0:
|
||||||
continue # xxx ignore fbitsize for now
|
continue # xxx ignore fbitsize for now
|
||||||
check(layout[i], ffi.offsetof(BStruct, fname),
|
check(layout[i], ffi.offsetof(BStruct, fname),
|
||||||
|
@ -354,11 +387,20 @@ class VGenericEngine(object):
|
||||||
# ----------
|
# ----------
|
||||||
# constants, likely declared with '#define'
|
# constants, likely declared with '#define'
|
||||||
|
|
||||||
def _generate_gen_const(self, is_int, name, tp=None, category='const'):
|
def _generate_gen_const(self, is_int, name, tp=None, category='const',
|
||||||
|
check_value=None):
|
||||||
prnt = self._prnt
|
prnt = self._prnt
|
||||||
funcname = '_cffi_%s_%s' % (category, name)
|
funcname = '_cffi_%s_%s' % (category, name)
|
||||||
self.export_symbols.append(funcname)
|
self.export_symbols.append(funcname)
|
||||||
if is_int:
|
if check_value is not None:
|
||||||
|
assert is_int
|
||||||
|
assert category == 'const'
|
||||||
|
prnt('int %s(char *out_error)' % funcname)
|
||||||
|
prnt('{')
|
||||||
|
self._check_int_constant_value(name, check_value)
|
||||||
|
prnt(' return 0;')
|
||||||
|
prnt('}')
|
||||||
|
elif is_int:
|
||||||
assert category == 'const'
|
assert category == 'const'
|
||||||
prnt('int %s(long long *out_value)' % funcname)
|
prnt('int %s(long long *out_value)' % funcname)
|
||||||
prnt('{')
|
prnt('{')
|
||||||
|
@ -367,12 +409,17 @@ class VGenericEngine(object):
|
||||||
prnt('}')
|
prnt('}')
|
||||||
else:
|
else:
|
||||||
assert tp is not None
|
assert tp is not None
|
||||||
prnt(tp.get_c_name(' %s(void)' % funcname, name),)
|
assert check_value is None
|
||||||
prnt('{')
|
|
||||||
if category == 'var':
|
if category == 'var':
|
||||||
ampersand = '&'
|
ampersand = '&'
|
||||||
else:
|
else:
|
||||||
ampersand = ''
|
ampersand = ''
|
||||||
|
extra = ''
|
||||||
|
if category == 'const' and isinstance(tp, model.StructOrUnion):
|
||||||
|
extra = 'const *'
|
||||||
|
ampersand = '&'
|
||||||
|
prnt(tp.get_c_name(' %s%s(void)' % (extra, funcname), name))
|
||||||
|
prnt('{')
|
||||||
prnt(' return (%s%s);' % (ampersand, name))
|
prnt(' return (%s%s);' % (ampersand, name))
|
||||||
prnt('}')
|
prnt('}')
|
||||||
prnt()
|
prnt()
|
||||||
|
@ -383,9 +430,13 @@ class VGenericEngine(object):
|
||||||
|
|
||||||
_loading_gen_constant = _loaded_noop
|
_loading_gen_constant = _loaded_noop
|
||||||
|
|
||||||
def _load_constant(self, is_int, tp, name, module):
|
def _load_constant(self, is_int, tp, name, module, check_value=None):
|
||||||
funcname = '_cffi_const_%s' % name
|
funcname = '_cffi_const_%s' % name
|
||||||
if is_int:
|
if check_value is not None:
|
||||||
|
assert is_int
|
||||||
|
self._load_known_int_constant(module, funcname)
|
||||||
|
value = check_value
|
||||||
|
elif is_int:
|
||||||
BType = self.ffi._typeof_locked("long long*")[0]
|
BType = self.ffi._typeof_locked("long long*")[0]
|
||||||
BFunc = self.ffi._typeof_locked("int(*)(long long*)")[0]
|
BFunc = self.ffi._typeof_locked("int(*)(long long*)")[0]
|
||||||
function = module.load_function(BFunc, funcname)
|
function = module.load_function(BFunc, funcname)
|
||||||
|
@ -396,9 +447,15 @@ class VGenericEngine(object):
|
||||||
BLongLong = self.ffi._typeof_locked("long long")[0]
|
BLongLong = self.ffi._typeof_locked("long long")[0]
|
||||||
value += (1 << (8*self.ffi.sizeof(BLongLong)))
|
value += (1 << (8*self.ffi.sizeof(BLongLong)))
|
||||||
else:
|
else:
|
||||||
BFunc = self.ffi._typeof_locked(tp.get_c_name('(*)(void)', name))[0]
|
assert check_value is None
|
||||||
|
fntypeextra = '(*)(void)'
|
||||||
|
if isinstance(tp, model.StructOrUnion):
|
||||||
|
fntypeextra = '*' + fntypeextra
|
||||||
|
BFunc = self.ffi._typeof_locked(tp.get_c_name(fntypeextra, name))[0]
|
||||||
function = module.load_function(BFunc, funcname)
|
function = module.load_function(BFunc, funcname)
|
||||||
value = function()
|
value = function()
|
||||||
|
if isinstance(tp, model.StructOrUnion):
|
||||||
|
value = value[0]
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def _loaded_gen_constant(self, tp, name, module, library):
|
def _loaded_gen_constant(self, tp, name, module, library):
|
||||||
|
@ -410,6 +467,36 @@ class VGenericEngine(object):
|
||||||
# ----------
|
# ----------
|
||||||
# enums
|
# enums
|
||||||
|
|
||||||
|
def _check_int_constant_value(self, name, value):
|
||||||
|
prnt = self._prnt
|
||||||
|
if value <= 0:
|
||||||
|
prnt(' if ((%s) > 0 || (long)(%s) != %dL) {' % (
|
||||||
|
name, name, value))
|
||||||
|
else:
|
||||||
|
prnt(' if ((%s) <= 0 || (unsigned long)(%s) != %dUL) {' % (
|
||||||
|
name, name, value))
|
||||||
|
prnt(' char buf[64];')
|
||||||
|
prnt(' if ((%s) <= 0)' % name)
|
||||||
|
prnt(' sprintf(buf, "%%ld", (long)(%s));' % name)
|
||||||
|
prnt(' else')
|
||||||
|
prnt(' sprintf(buf, "%%lu", (unsigned long)(%s));' %
|
||||||
|
name)
|
||||||
|
prnt(' sprintf(out_error, "%s has the real value %s, not %s",')
|
||||||
|
prnt(' "%s", buf, "%d");' % (name[:100], value))
|
||||||
|
prnt(' return -1;')
|
||||||
|
prnt(' }')
|
||||||
|
|
||||||
|
def _load_known_int_constant(self, module, funcname):
|
||||||
|
BType = self.ffi._typeof_locked("char[]")[0]
|
||||||
|
BFunc = self.ffi._typeof_locked("int(*)(char*)")[0]
|
||||||
|
function = module.load_function(BFunc, funcname)
|
||||||
|
p = self.ffi.new(BType, 256)
|
||||||
|
if function(p) < 0:
|
||||||
|
error = self.ffi.string(p)
|
||||||
|
if sys.version_info >= (3,):
|
||||||
|
error = str(error, 'utf-8')
|
||||||
|
raise ffiplatform.VerificationError(error)
|
||||||
|
|
||||||
def _enum_funcname(self, prefix, name):
|
def _enum_funcname(self, prefix, name):
|
||||||
# "$enum_$1" => "___D_enum____D_1"
|
# "$enum_$1" => "___D_enum____D_1"
|
||||||
name = name.replace('$', '___D_')
|
name = name.replace('$', '___D_')
|
||||||
|
@ -427,24 +514,7 @@ class VGenericEngine(object):
|
||||||
prnt('int %s(char *out_error)' % funcname)
|
prnt('int %s(char *out_error)' % funcname)
|
||||||
prnt('{')
|
prnt('{')
|
||||||
for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues):
|
for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues):
|
||||||
if enumvalue < 0:
|
self._check_int_constant_value(enumerator, enumvalue)
|
||||||
prnt(' if ((%s) >= 0 || (long)(%s) != %dL) {' % (
|
|
||||||
enumerator, enumerator, enumvalue))
|
|
||||||
else:
|
|
||||||
prnt(' if ((%s) < 0 || (unsigned long)(%s) != %dUL) {' % (
|
|
||||||
enumerator, enumerator, enumvalue))
|
|
||||||
prnt(' char buf[64];')
|
|
||||||
prnt(' if ((%s) < 0)' % enumerator)
|
|
||||||
prnt(' sprintf(buf, "%%ld", (long)(%s));' % enumerator)
|
|
||||||
prnt(' else')
|
|
||||||
prnt(' sprintf(buf, "%%lu", (unsigned long)(%s));' %
|
|
||||||
enumerator)
|
|
||||||
prnt(' sprintf(out_error,'
|
|
||||||
' "%s has the real value %s, not %s",')
|
|
||||||
prnt(' "%s", buf, "%d");' % (
|
|
||||||
enumerator[:100], enumvalue))
|
|
||||||
prnt(' return -1;')
|
|
||||||
prnt(' }')
|
|
||||||
prnt(' return 0;')
|
prnt(' return 0;')
|
||||||
prnt('}')
|
prnt('}')
|
||||||
prnt()
|
prnt()
|
||||||
|
@ -456,16 +526,8 @@ class VGenericEngine(object):
|
||||||
tp.enumvalues = tuple(enumvalues)
|
tp.enumvalues = tuple(enumvalues)
|
||||||
tp.partial_resolved = True
|
tp.partial_resolved = True
|
||||||
else:
|
else:
|
||||||
BType = self.ffi._typeof_locked("char[]")[0]
|
|
||||||
BFunc = self.ffi._typeof_locked("int(*)(char*)")[0]
|
|
||||||
funcname = self._enum_funcname(prefix, name)
|
funcname = self._enum_funcname(prefix, name)
|
||||||
function = module.load_function(BFunc, funcname)
|
self._load_known_int_constant(module, funcname)
|
||||||
p = self.ffi.new(BType, 256)
|
|
||||||
if function(p) < 0:
|
|
||||||
error = self.ffi.string(p)
|
|
||||||
if sys.version_info >= (3,):
|
|
||||||
error = str(error, 'utf-8')
|
|
||||||
raise ffiplatform.VerificationError(error)
|
|
||||||
|
|
||||||
def _loaded_gen_enum(self, tp, name, module, library):
|
def _loaded_gen_enum(self, tp, name, module, library):
|
||||||
for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues):
|
for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues):
|
||||||
|
@ -476,13 +538,21 @@ class VGenericEngine(object):
|
||||||
# macros: for now only for integers
|
# macros: for now only for integers
|
||||||
|
|
||||||
def _generate_gen_macro_decl(self, tp, name):
|
def _generate_gen_macro_decl(self, tp, name):
|
||||||
assert tp == '...'
|
if tp == '...':
|
||||||
self._generate_gen_const(True, name)
|
check_value = None
|
||||||
|
else:
|
||||||
|
check_value = tp # an integer
|
||||||
|
self._generate_gen_const(True, name, check_value=check_value)
|
||||||
|
|
||||||
_loading_gen_macro = _loaded_noop
|
_loading_gen_macro = _loaded_noop
|
||||||
|
|
||||||
def _loaded_gen_macro(self, tp, name, module, library):
|
def _loaded_gen_macro(self, tp, name, module, library):
|
||||||
value = self._load_constant(True, tp, name, module)
|
if tp == '...':
|
||||||
|
check_value = None
|
||||||
|
else:
|
||||||
|
check_value = tp # an integer
|
||||||
|
value = self._load_constant(True, tp, name, module,
|
||||||
|
check_value=check_value)
|
||||||
setattr(library, name, value)
|
setattr(library, name, value)
|
||||||
type(library)._cffi_dir.append(name)
|
type(library)._cffi_dir.append(name)
|
||||||
|
|
||||||
|
@ -565,6 +635,24 @@ cffimod_header = r'''
|
||||||
typedef unsigned __int16 uint16_t;
|
typedef unsigned __int16 uint16_t;
|
||||||
typedef unsigned __int32 uint32_t;
|
typedef unsigned __int32 uint32_t;
|
||||||
typedef unsigned __int64 uint64_t;
|
typedef unsigned __int64 uint64_t;
|
||||||
|
typedef __int8 int_least8_t;
|
||||||
|
typedef __int16 int_least16_t;
|
||||||
|
typedef __int32 int_least32_t;
|
||||||
|
typedef __int64 int_least64_t;
|
||||||
|
typedef unsigned __int8 uint_least8_t;
|
||||||
|
typedef unsigned __int16 uint_least16_t;
|
||||||
|
typedef unsigned __int32 uint_least32_t;
|
||||||
|
typedef unsigned __int64 uint_least64_t;
|
||||||
|
typedef __int8 int_fast8_t;
|
||||||
|
typedef __int16 int_fast16_t;
|
||||||
|
typedef __int32 int_fast32_t;
|
||||||
|
typedef __int64 int_fast64_t;
|
||||||
|
typedef unsigned __int8 uint_fast8_t;
|
||||||
|
typedef unsigned __int16 uint_fast16_t;
|
||||||
|
typedef unsigned __int32 uint_fast32_t;
|
||||||
|
typedef unsigned __int64 uint_fast64_t;
|
||||||
|
typedef __int64 intmax_t;
|
||||||
|
typedef unsigned __int64 uintmax_t;
|
||||||
# else
|
# else
|
||||||
# include <stdint.h>
|
# include <stdint.h>
|
||||||
# endif
|
# endif
|
||||||
|
|
|
@ -1,12 +1,47 @@
|
||||||
import sys, os, binascii, imp, shutil
|
import sys, os, binascii, shutil, io
|
||||||
from . import __version__
|
from . import __version_verifier_modules__
|
||||||
from . import ffiplatform
|
from . import ffiplatform
|
||||||
|
|
||||||
|
if sys.version_info >= (3, 3):
|
||||||
|
import importlib.machinery
|
||||||
|
def _extension_suffixes():
|
||||||
|
return importlib.machinery.EXTENSION_SUFFIXES[:]
|
||||||
|
else:
|
||||||
|
import imp
|
||||||
|
def _extension_suffixes():
|
||||||
|
return [suffix for suffix, _, type in imp.get_suffixes()
|
||||||
|
if type == imp.C_EXTENSION]
|
||||||
|
|
||||||
|
|
||||||
|
if sys.version_info >= (3,):
|
||||||
|
NativeIO = io.StringIO
|
||||||
|
else:
|
||||||
|
class NativeIO(io.BytesIO):
|
||||||
|
def write(self, s):
|
||||||
|
if isinstance(s, unicode):
|
||||||
|
s = s.encode('ascii')
|
||||||
|
super(NativeIO, self).write(s)
|
||||||
|
|
||||||
|
def _hack_at_distutils():
|
||||||
|
# Windows-only workaround for some configurations: see
|
||||||
|
# https://bugs.python.org/issue23246 (Python 2.7 with
|
||||||
|
# a specific MS compiler suite download)
|
||||||
|
if sys.platform == "win32":
|
||||||
|
try:
|
||||||
|
import setuptools # for side-effects, patches distutils
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Verifier(object):
|
class Verifier(object):
|
||||||
|
|
||||||
def __init__(self, ffi, preamble, tmpdir=None, modulename=None,
|
def __init__(self, ffi, preamble, tmpdir=None, modulename=None,
|
||||||
ext_package=None, tag='', force_generic_engine=False, **kwds):
|
ext_package=None, tag='', force_generic_engine=False,
|
||||||
|
source_extension='.c', flags=None, relative_to=None, **kwds):
|
||||||
|
if ffi._parser._uses_new_feature:
|
||||||
|
raise ffiplatform.VerificationError(
|
||||||
|
"feature not supported with ffi.verify(), but only "
|
||||||
|
"with ffi.set_source(): %s" % (ffi._parser._uses_new_feature,))
|
||||||
self.ffi = ffi
|
self.ffi = ffi
|
||||||
self.preamble = preamble
|
self.preamble = preamble
|
||||||
if not modulename:
|
if not modulename:
|
||||||
|
@ -14,14 +49,15 @@ class Verifier(object):
|
||||||
vengine_class = _locate_engine_class(ffi, force_generic_engine)
|
vengine_class = _locate_engine_class(ffi, force_generic_engine)
|
||||||
self._vengine = vengine_class(self)
|
self._vengine = vengine_class(self)
|
||||||
self._vengine.patch_extension_kwds(kwds)
|
self._vengine.patch_extension_kwds(kwds)
|
||||||
self.kwds = kwds
|
self.flags = flags
|
||||||
|
self.kwds = self.make_relative_to(kwds, relative_to)
|
||||||
#
|
#
|
||||||
if modulename:
|
if modulename:
|
||||||
if tag:
|
if tag:
|
||||||
raise TypeError("can't specify both 'modulename' and 'tag'")
|
raise TypeError("can't specify both 'modulename' and 'tag'")
|
||||||
else:
|
else:
|
||||||
key = '\x00'.join([sys.version[:3], __version__, preamble,
|
key = '\x00'.join([sys.version[:3], __version_verifier_modules__,
|
||||||
flattened_kwds] +
|
preamble, flattened_kwds] +
|
||||||
ffi._cdefsources)
|
ffi._cdefsources)
|
||||||
if sys.version_info >= (3,):
|
if sys.version_info >= (3,):
|
||||||
key = key.encode('utf-8')
|
key = key.encode('utf-8')
|
||||||
|
@ -33,7 +69,7 @@ class Verifier(object):
|
||||||
k1, k2)
|
k1, k2)
|
||||||
suffix = _get_so_suffixes()[0]
|
suffix = _get_so_suffixes()[0]
|
||||||
self.tmpdir = tmpdir or _caller_dir_pycache()
|
self.tmpdir = tmpdir or _caller_dir_pycache()
|
||||||
self.sourcefilename = os.path.join(self.tmpdir, modulename + '.c')
|
self.sourcefilename = os.path.join(self.tmpdir, modulename + source_extension)
|
||||||
self.modulefilename = os.path.join(self.tmpdir, modulename + suffix)
|
self.modulefilename = os.path.join(self.tmpdir, modulename + suffix)
|
||||||
self.ext_package = ext_package
|
self.ext_package = ext_package
|
||||||
self._has_source = False
|
self._has_source = False
|
||||||
|
@ -86,6 +122,7 @@ class Verifier(object):
|
||||||
return basename
|
return basename
|
||||||
|
|
||||||
def get_extension(self):
|
def get_extension(self):
|
||||||
|
_hack_at_distutils() # backward compatibility hack
|
||||||
if not self._has_source:
|
if not self._has_source:
|
||||||
with self.ffi._lock:
|
with self.ffi._lock:
|
||||||
if not self._has_source:
|
if not self._has_source:
|
||||||
|
@ -97,6 +134,20 @@ class Verifier(object):
|
||||||
def generates_python_module(self):
|
def generates_python_module(self):
|
||||||
return self._vengine._gen_python_module
|
return self._vengine._gen_python_module
|
||||||
|
|
||||||
|
def make_relative_to(self, kwds, relative_to):
|
||||||
|
if relative_to and os.path.dirname(relative_to):
|
||||||
|
dirname = os.path.dirname(relative_to)
|
||||||
|
kwds = kwds.copy()
|
||||||
|
for key in ffiplatform.LIST_OF_FILE_NAMES:
|
||||||
|
if key in kwds:
|
||||||
|
lst = kwds[key]
|
||||||
|
if not isinstance(lst, (list, tuple)):
|
||||||
|
raise TypeError("keyword '%s' should be a list or tuple"
|
||||||
|
% (key,))
|
||||||
|
lst = [os.path.join(dirname, fn) for fn in lst]
|
||||||
|
kwds[key] = lst
|
||||||
|
return kwds
|
||||||
|
|
||||||
# ----------
|
# ----------
|
||||||
|
|
||||||
def _locate_module(self):
|
def _locate_module(self):
|
||||||
|
@ -118,19 +169,36 @@ class Verifier(object):
|
||||||
self._vengine.collect_types()
|
self._vengine.collect_types()
|
||||||
self._has_module = True
|
self._has_module = True
|
||||||
|
|
||||||
def _write_source(self, file=None):
|
def _write_source_to(self, file):
|
||||||
must_close = (file is None)
|
|
||||||
if must_close:
|
|
||||||
_ensure_dir(self.sourcefilename)
|
|
||||||
file = open(self.sourcefilename, 'w')
|
|
||||||
self._vengine._f = file
|
self._vengine._f = file
|
||||||
try:
|
try:
|
||||||
self._vengine.write_source_to_f()
|
self._vengine.write_source_to_f()
|
||||||
finally:
|
finally:
|
||||||
del self._vengine._f
|
del self._vengine._f
|
||||||
if must_close:
|
|
||||||
file.close()
|
def _write_source(self, file=None):
|
||||||
if must_close:
|
if file is not None:
|
||||||
|
self._write_source_to(file)
|
||||||
|
else:
|
||||||
|
# Write our source file to an in memory file.
|
||||||
|
f = NativeIO()
|
||||||
|
self._write_source_to(f)
|
||||||
|
source_data = f.getvalue()
|
||||||
|
|
||||||
|
# Determine if this matches the current file
|
||||||
|
if os.path.exists(self.sourcefilename):
|
||||||
|
with open(self.sourcefilename, "r") as fp:
|
||||||
|
needs_written = not (fp.read() == source_data)
|
||||||
|
else:
|
||||||
|
needs_written = True
|
||||||
|
|
||||||
|
# Actually write the file out if it doesn't match
|
||||||
|
if needs_written:
|
||||||
|
_ensure_dir(self.sourcefilename)
|
||||||
|
with open(self.sourcefilename, "w") as fp:
|
||||||
|
fp.write(source_data)
|
||||||
|
|
||||||
|
# Set this flag
|
||||||
self._has_source = True
|
self._has_source = True
|
||||||
|
|
||||||
def _compile_module(self):
|
def _compile_module(self):
|
||||||
|
@ -148,6 +216,9 @@ class Verifier(object):
|
||||||
|
|
||||||
def _load_library(self):
|
def _load_library(self):
|
||||||
assert self._has_module
|
assert self._has_module
|
||||||
|
if self.flags is not None:
|
||||||
|
return self._vengine.load_library(self.flags)
|
||||||
|
else:
|
||||||
return self._vengine.load_library()
|
return self._vengine.load_library()
|
||||||
|
|
||||||
# ____________________________________________________________
|
# ____________________________________________________________
|
||||||
|
@ -181,6 +252,9 @@ _TMPDIR = None
|
||||||
def _caller_dir_pycache():
|
def _caller_dir_pycache():
|
||||||
if _TMPDIR:
|
if _TMPDIR:
|
||||||
return _TMPDIR
|
return _TMPDIR
|
||||||
|
result = os.environ.get('CFFI_TMPDIR')
|
||||||
|
if result:
|
||||||
|
return result
|
||||||
filename = sys._getframe(2).f_code.co_filename
|
filename = sys._getframe(2).f_code.co_filename
|
||||||
return os.path.abspath(os.path.join(os.path.dirname(filename),
|
return os.path.abspath(os.path.join(os.path.dirname(filename),
|
||||||
'__pycache__'))
|
'__pycache__'))
|
||||||
|
@ -222,11 +296,7 @@ def cleanup_tmpdir(tmpdir=None, keep_so=False):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def _get_so_suffixes():
|
def _get_so_suffixes():
|
||||||
suffixes = []
|
suffixes = _extension_suffixes()
|
||||||
for suffix, mode, type in imp.get_suffixes():
|
|
||||||
if type == imp.C_EXTENSION:
|
|
||||||
suffixes.append(suffix)
|
|
||||||
|
|
||||||
if not suffixes:
|
if not suffixes:
|
||||||
# bah, no C_EXTENSION available. Occurs on pypy without cpyext
|
# bah, no C_EXTENSION available. Occurs on pypy without cpyext
|
||||||
if sys.platform == 'win32':
|
if sys.platform == 'win32':
|
||||||
|
|
|
@ -1,217 +0,0 @@
|
||||||
AUTHORS.rst
|
|
||||||
CHANGELOG.rst
|
|
||||||
CONTRIBUTING.rst
|
|
||||||
LICENSE
|
|
||||||
MANIFEST.in
|
|
||||||
README.rst
|
|
||||||
setup.cfg
|
|
||||||
setup.py
|
|
||||||
cryptography/__about__.py
|
|
||||||
cryptography/__init__.py
|
|
||||||
cryptography/exceptions.py
|
|
||||||
cryptography/fernet.py
|
|
||||||
cryptography/utils.py
|
|
||||||
cryptography.egg-info/PKG-INFO
|
|
||||||
cryptography.egg-info/SOURCES.txt
|
|
||||||
cryptography.egg-info/dependency_links.txt
|
|
||||||
cryptography.egg-info/entry_points.txt
|
|
||||||
cryptography.egg-info/not-zip-safe
|
|
||||||
cryptography.egg-info/requires.txt
|
|
||||||
cryptography.egg-info/top_level.txt
|
|
||||||
cryptography/hazmat/__init__.py
|
|
||||||
cryptography/hazmat/backends/__init__.py
|
|
||||||
cryptography/hazmat/backends/interfaces.py
|
|
||||||
cryptography/hazmat/backends/multibackend.py
|
|
||||||
cryptography/hazmat/backends/commoncrypto/__init__.py
|
|
||||||
cryptography/hazmat/backends/commoncrypto/backend.py
|
|
||||||
cryptography/hazmat/backends/commoncrypto/ciphers.py
|
|
||||||
cryptography/hazmat/backends/commoncrypto/hashes.py
|
|
||||||
cryptography/hazmat/backends/commoncrypto/hmac.py
|
|
||||||
cryptography/hazmat/backends/openssl/__init__.py
|
|
||||||
cryptography/hazmat/backends/openssl/backend.py
|
|
||||||
cryptography/hazmat/backends/openssl/ciphers.py
|
|
||||||
cryptography/hazmat/backends/openssl/cmac.py
|
|
||||||
cryptography/hazmat/backends/openssl/dsa.py
|
|
||||||
cryptography/hazmat/backends/openssl/ec.py
|
|
||||||
cryptography/hazmat/backends/openssl/hashes.py
|
|
||||||
cryptography/hazmat/backends/openssl/hmac.py
|
|
||||||
cryptography/hazmat/backends/openssl/rsa.py
|
|
||||||
cryptography/hazmat/bindings/__init__.py
|
|
||||||
cryptography/hazmat/bindings/utils.py
|
|
||||||
cryptography/hazmat/bindings/__pycache__/_Cryptography_cffi_3e31f141x4000d087.c
|
|
||||||
cryptography/hazmat/bindings/commoncrypto/__init__.py
|
|
||||||
cryptography/hazmat/bindings/commoncrypto/binding.py
|
|
||||||
cryptography/hazmat/bindings/commoncrypto/cf.py
|
|
||||||
cryptography/hazmat/bindings/commoncrypto/common_cryptor.py
|
|
||||||
cryptography/hazmat/bindings/commoncrypto/common_digest.py
|
|
||||||
cryptography/hazmat/bindings/commoncrypto/common_hmac.py
|
|
||||||
cryptography/hazmat/bindings/commoncrypto/common_key_derivation.py
|
|
||||||
cryptography/hazmat/bindings/commoncrypto/secimport.py
|
|
||||||
cryptography/hazmat/bindings/commoncrypto/secitem.py
|
|
||||||
cryptography/hazmat/bindings/commoncrypto/seckey.py
|
|
||||||
cryptography/hazmat/bindings/commoncrypto/seckeychain.py
|
|
||||||
cryptography/hazmat/bindings/commoncrypto/sectransform.py
|
|
||||||
cryptography/hazmat/bindings/openssl/__init__.py
|
|
||||||
cryptography/hazmat/bindings/openssl/aes.py
|
|
||||||
cryptography/hazmat/bindings/openssl/asn1.py
|
|
||||||
cryptography/hazmat/bindings/openssl/bignum.py
|
|
||||||
cryptography/hazmat/bindings/openssl/binding.py
|
|
||||||
cryptography/hazmat/bindings/openssl/bio.py
|
|
||||||
cryptography/hazmat/bindings/openssl/cmac.py
|
|
||||||
cryptography/hazmat/bindings/openssl/cms.py
|
|
||||||
cryptography/hazmat/bindings/openssl/conf.py
|
|
||||||
cryptography/hazmat/bindings/openssl/crypto.py
|
|
||||||
cryptography/hazmat/bindings/openssl/dh.py
|
|
||||||
cryptography/hazmat/bindings/openssl/dsa.py
|
|
||||||
cryptography/hazmat/bindings/openssl/ec.py
|
|
||||||
cryptography/hazmat/bindings/openssl/ecdh.py
|
|
||||||
cryptography/hazmat/bindings/openssl/ecdsa.py
|
|
||||||
cryptography/hazmat/bindings/openssl/engine.py
|
|
||||||
cryptography/hazmat/bindings/openssl/err.py
|
|
||||||
cryptography/hazmat/bindings/openssl/evp.py
|
|
||||||
cryptography/hazmat/bindings/openssl/hmac.py
|
|
||||||
cryptography/hazmat/bindings/openssl/nid.py
|
|
||||||
cryptography/hazmat/bindings/openssl/objects.py
|
|
||||||
cryptography/hazmat/bindings/openssl/opensslv.py
|
|
||||||
cryptography/hazmat/bindings/openssl/osrandom_engine.py
|
|
||||||
cryptography/hazmat/bindings/openssl/pem.py
|
|
||||||
cryptography/hazmat/bindings/openssl/pkcs12.py
|
|
||||||
cryptography/hazmat/bindings/openssl/pkcs7.py
|
|
||||||
cryptography/hazmat/bindings/openssl/rand.py
|
|
||||||
cryptography/hazmat/bindings/openssl/rsa.py
|
|
||||||
cryptography/hazmat/bindings/openssl/ssl.py
|
|
||||||
cryptography/hazmat/bindings/openssl/x509.py
|
|
||||||
cryptography/hazmat/bindings/openssl/x509_vfy.py
|
|
||||||
cryptography/hazmat/bindings/openssl/x509name.py
|
|
||||||
cryptography/hazmat/bindings/openssl/x509v3.py
|
|
||||||
cryptography/hazmat/primitives/__init__.py
|
|
||||||
cryptography/hazmat/primitives/cmac.py
|
|
||||||
cryptography/hazmat/primitives/constant_time.py
|
|
||||||
cryptography/hazmat/primitives/hashes.py
|
|
||||||
cryptography/hazmat/primitives/hmac.py
|
|
||||||
cryptography/hazmat/primitives/interfaces.py
|
|
||||||
cryptography/hazmat/primitives/padding.py
|
|
||||||
cryptography/hazmat/primitives/serialization.py
|
|
||||||
cryptography/hazmat/primitives/__pycache__/_Cryptography_cffi_7ab3712bx4f158fee.c
|
|
||||||
cryptography/hazmat/primitives/__pycache__/_Cryptography_cffi_dd416c1exc1767c5a.c
|
|
||||||
cryptography/hazmat/primitives/asymmetric/__init__.py
|
|
||||||
cryptography/hazmat/primitives/asymmetric/dsa.py
|
|
||||||
cryptography/hazmat/primitives/asymmetric/ec.py
|
|
||||||
cryptography/hazmat/primitives/asymmetric/padding.py
|
|
||||||
cryptography/hazmat/primitives/asymmetric/rsa.py
|
|
||||||
cryptography/hazmat/primitives/ciphers/__init__.py
|
|
||||||
cryptography/hazmat/primitives/ciphers/algorithms.py
|
|
||||||
cryptography/hazmat/primitives/ciphers/base.py
|
|
||||||
cryptography/hazmat/primitives/ciphers/modes.py
|
|
||||||
cryptography/hazmat/primitives/kdf/__init__.py
|
|
||||||
cryptography/hazmat/primitives/kdf/hkdf.py
|
|
||||||
cryptography/hazmat/primitives/kdf/pbkdf2.py
|
|
||||||
cryptography/hazmat/primitives/src/constant_time.c
|
|
||||||
cryptography/hazmat/primitives/src/constant_time.h
|
|
||||||
cryptography/hazmat/primitives/twofactor/__init__.py
|
|
||||||
cryptography/hazmat/primitives/twofactor/hotp.py
|
|
||||||
cryptography/hazmat/primitives/twofactor/totp.py
|
|
||||||
docs/Makefile
|
|
||||||
docs/api-stability.rst
|
|
||||||
docs/changelog.rst
|
|
||||||
docs/community.rst
|
|
||||||
docs/conf.py
|
|
||||||
docs/cryptography-docs.py
|
|
||||||
docs/doing-a-release.rst
|
|
||||||
docs/exceptions.rst
|
|
||||||
docs/faq.rst
|
|
||||||
docs/fernet.rst
|
|
||||||
docs/glossary.rst
|
|
||||||
docs/index.rst
|
|
||||||
docs/installation.rst
|
|
||||||
docs/limitations.rst
|
|
||||||
docs/make.bat
|
|
||||||
docs/random-numbers.rst
|
|
||||||
docs/security.rst
|
|
||||||
docs/spelling_wordlist.txt
|
|
||||||
docs/_static/.keep
|
|
||||||
docs/development/c-bindings.rst
|
|
||||||
docs/development/getting-started.rst
|
|
||||||
docs/development/index.rst
|
|
||||||
docs/development/reviewing-patches.rst
|
|
||||||
docs/development/submitting-patches.rst
|
|
||||||
docs/development/test-vectors.rst
|
|
||||||
docs/development/custom-vectors/cast5.rst
|
|
||||||
docs/development/custom-vectors/idea.rst
|
|
||||||
docs/development/custom-vectors/seed.rst
|
|
||||||
docs/development/custom-vectors/cast5/generate_cast5.py
|
|
||||||
docs/development/custom-vectors/cast5/verify_cast5.go
|
|
||||||
docs/development/custom-vectors/idea/generate_idea.py
|
|
||||||
docs/development/custom-vectors/idea/verify_idea.py
|
|
||||||
docs/development/custom-vectors/seed/generate_seed.py
|
|
||||||
docs/development/custom-vectors/seed/verify_seed.py
|
|
||||||
docs/hazmat/backends/commoncrypto.rst
|
|
||||||
docs/hazmat/backends/index.rst
|
|
||||||
docs/hazmat/backends/interfaces.rst
|
|
||||||
docs/hazmat/backends/multibackend.rst
|
|
||||||
docs/hazmat/backends/openssl.rst
|
|
||||||
docs/hazmat/bindings/commoncrypto.rst
|
|
||||||
docs/hazmat/bindings/index.rst
|
|
||||||
docs/hazmat/bindings/openssl.rst
|
|
||||||
docs/hazmat/primitives/constant-time.rst
|
|
||||||
docs/hazmat/primitives/cryptographic-hashes.rst
|
|
||||||
docs/hazmat/primitives/index.rst
|
|
||||||
docs/hazmat/primitives/interfaces.rst
|
|
||||||
docs/hazmat/primitives/key-derivation-functions.rst
|
|
||||||
docs/hazmat/primitives/padding.rst
|
|
||||||
docs/hazmat/primitives/symmetric-encryption.rst
|
|
||||||
docs/hazmat/primitives/twofactor.rst
|
|
||||||
docs/hazmat/primitives/asymmetric/dsa.rst
|
|
||||||
docs/hazmat/primitives/asymmetric/ec.rst
|
|
||||||
docs/hazmat/primitives/asymmetric/index.rst
|
|
||||||
docs/hazmat/primitives/asymmetric/padding.rst
|
|
||||||
docs/hazmat/primitives/asymmetric/rsa.rst
|
|
||||||
docs/hazmat/primitives/asymmetric/serialization.rst
|
|
||||||
docs/hazmat/primitives/mac/cmac.rst
|
|
||||||
docs/hazmat/primitives/mac/hmac.rst
|
|
||||||
docs/hazmat/primitives/mac/index.rst
|
|
||||||
tests/__init__.py
|
|
||||||
tests/conftest.py
|
|
||||||
tests/test_fernet.py
|
|
||||||
tests/test_utils.py
|
|
||||||
tests/utils.py
|
|
||||||
tests/hazmat/__init__.py
|
|
||||||
tests/hazmat/backends/__init__.py
|
|
||||||
tests/hazmat/backends/test_commoncrypto.py
|
|
||||||
tests/hazmat/backends/test_multibackend.py
|
|
||||||
tests/hazmat/backends/test_openssl.py
|
|
||||||
tests/hazmat/bindings/test_commoncrypto.py
|
|
||||||
tests/hazmat/bindings/test_openssl.py
|
|
||||||
tests/hazmat/bindings/test_utils.py
|
|
||||||
tests/hazmat/primitives/__init__.py
|
|
||||||
tests/hazmat/primitives/fixtures_dsa.py
|
|
||||||
tests/hazmat/primitives/fixtures_rsa.py
|
|
||||||
tests/hazmat/primitives/test_3des.py
|
|
||||||
tests/hazmat/primitives/test_aes.py
|
|
||||||
tests/hazmat/primitives/test_arc4.py
|
|
||||||
tests/hazmat/primitives/test_block.py
|
|
||||||
tests/hazmat/primitives/test_blowfish.py
|
|
||||||
tests/hazmat/primitives/test_camellia.py
|
|
||||||
tests/hazmat/primitives/test_cast5.py
|
|
||||||
tests/hazmat/primitives/test_ciphers.py
|
|
||||||
tests/hazmat/primitives/test_cmac.py
|
|
||||||
tests/hazmat/primitives/test_constant_time.py
|
|
||||||
tests/hazmat/primitives/test_dsa.py
|
|
||||||
tests/hazmat/primitives/test_ec.py
|
|
||||||
tests/hazmat/primitives/test_hash_vectors.py
|
|
||||||
tests/hazmat/primitives/test_hashes.py
|
|
||||||
tests/hazmat/primitives/test_hkdf.py
|
|
||||||
tests/hazmat/primitives/test_hkdf_vectors.py
|
|
||||||
tests/hazmat/primitives/test_hmac.py
|
|
||||||
tests/hazmat/primitives/test_hmac_vectors.py
|
|
||||||
tests/hazmat/primitives/test_idea.py
|
|
||||||
tests/hazmat/primitives/test_padding.py
|
|
||||||
tests/hazmat/primitives/test_pbkdf2hmac.py
|
|
||||||
tests/hazmat/primitives/test_pbkdf2hmac_vectors.py
|
|
||||||
tests/hazmat/primitives/test_rsa.py
|
|
||||||
tests/hazmat/primitives/test_seed.py
|
|
||||||
tests/hazmat/primitives/test_serialization.py
|
|
||||||
tests/hazmat/primitives/utils.py
|
|
||||||
tests/hazmat/primitives/twofactor/__init__.py
|
|
||||||
tests/hazmat/primitives/twofactor/test_hotp.py
|
|
||||||
tests/hazmat/primitives/twofactor/test_totp.py
|
|
|
@ -1,3 +0,0 @@
|
||||||
cffi>=0.8
|
|
||||||
six>=1.4.1
|
|
||||||
setuptools
|
|
|
@ -1,4 +0,0 @@
|
||||||
cryptography
|
|
||||||
_Cryptography_cffi_7ab3712bx4f158fee
|
|
||||||
_Cryptography_cffi_3e31f141x4000d087
|
|
||||||
_Cryptography_cffi_dd416c1exc1767c5a
|
|
|
@ -1,15 +1,15 @@
|
||||||
Metadata-Version: 1.1
|
Metadata-Version: 1.1
|
||||||
Name: cryptography
|
Name: cryptography
|
||||||
Version: 0.6
|
Version: 1.1
|
||||||
Summary: cryptography is a package which provides cryptographic recipes and primitives to Python developers.
|
Summary: cryptography is a package which provides cryptographic recipes and primitives to Python developers.
|
||||||
Home-page: https://github.com/pyca/cryptography
|
Home-page: https://github.com/pyca/cryptography
|
||||||
Author: The cryptography developers
|
Author: The cryptography developers
|
||||||
Author-email: cryptography-dev@python.org
|
Author-email: cryptography-dev@python.org
|
||||||
License: Apache License, Version 2.0
|
License: BSD or Apache License, Version 2.0
|
||||||
Description: Cryptography
|
Description: Cryptography
|
||||||
============
|
============
|
||||||
|
|
||||||
.. image:: https://pypip.in/version/cryptography/badge.svg
|
.. image:: https://img.shields.io/pypi/v/cryptography.svg
|
||||||
:target: https://pypi.python.org/pypi/cryptography/
|
:target: https://pypi.python.org/pypi/cryptography/
|
||||||
:alt: Latest Version
|
:alt: Latest Version
|
||||||
|
|
||||||
|
@ -20,13 +20,13 @@ Description: Cryptography
|
||||||
.. image:: https://travis-ci.org/pyca/cryptography.svg?branch=master
|
.. image:: https://travis-ci.org/pyca/cryptography.svg?branch=master
|
||||||
:target: https://travis-ci.org/pyca/cryptography
|
:target: https://travis-ci.org/pyca/cryptography
|
||||||
|
|
||||||
.. image:: https://coveralls.io/repos/pyca/cryptography/badge.png?branch=master
|
.. image:: https://codecov.io/github/pyca/cryptography/coverage.svg?branch=master
|
||||||
:target: https://coveralls.io/r/pyca/cryptography?branch=master
|
:target: https://codecov.io/github/pyca/cryptography?branch=master
|
||||||
|
|
||||||
|
|
||||||
``cryptography`` is a package which provides cryptographic recipes and
|
``cryptography`` is a package which provides cryptographic recipes and
|
||||||
primitives to Python developers. Our goal is for it to be your "cryptographic
|
primitives to Python developers. Our goal is for it to be your "cryptographic
|
||||||
standard library". It supports Python 2.6-2.7, Python 3.2+, and PyPy.
|
standard library". It supports Python 2.6-2.7, Python 3.3+, and PyPy 2.6+.
|
||||||
|
|
||||||
``cryptography`` includes both high level recipes, and low level interfaces to
|
``cryptography`` includes both high level recipes, and low level interfaces to
|
||||||
common cryptographic algorithms such as symmetric ciphers, message digests and
|
common cryptographic algorithms such as symmetric ciphers, message digests and
|
||||||
|
@ -65,6 +65,7 @@ Description: Cryptography
|
||||||
Platform: UNKNOWN
|
Platform: UNKNOWN
|
||||||
Classifier: Intended Audience :: Developers
|
Classifier: Intended Audience :: Developers
|
||||||
Classifier: License :: OSI Approved :: Apache Software License
|
Classifier: License :: OSI Approved :: Apache Software License
|
||||||
|
Classifier: License :: OSI Approved :: BSD License
|
||||||
Classifier: Natural Language :: English
|
Classifier: Natural Language :: English
|
||||||
Classifier: Operating System :: MacOS :: MacOS X
|
Classifier: Operating System :: MacOS :: MacOS X
|
||||||
Classifier: Operating System :: POSIX
|
Classifier: Operating System :: POSIX
|
||||||
|
@ -76,9 +77,9 @@ Classifier: Programming Language :: Python :: 2
|
||||||
Classifier: Programming Language :: Python :: 2.6
|
Classifier: Programming Language :: Python :: 2.6
|
||||||
Classifier: Programming Language :: Python :: 2.7
|
Classifier: Programming Language :: Python :: 2.7
|
||||||
Classifier: Programming Language :: Python :: 3
|
Classifier: Programming Language :: Python :: 3
|
||||||
Classifier: Programming Language :: Python :: 3.2
|
|
||||||
Classifier: Programming Language :: Python :: 3.3
|
Classifier: Programming Language :: Python :: 3.3
|
||||||
Classifier: Programming Language :: Python :: 3.4
|
Classifier: Programming Language :: Python :: 3.4
|
||||||
|
Classifier: Programming Language :: Python :: 3.5
|
||||||
Classifier: Programming Language :: Python :: Implementation :: CPython
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
||||||
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
||||||
Classifier: Topic :: Security :: Cryptography
|
Classifier: Topic :: Security :: Cryptography
|
|
@ -0,0 +1,260 @@
|
||||||
|
AUTHORS.rst
|
||||||
|
CHANGELOG.rst
|
||||||
|
CONTRIBUTING.rst
|
||||||
|
LICENSE
|
||||||
|
LICENSE.APACHE
|
||||||
|
LICENSE.BSD
|
||||||
|
MANIFEST.in
|
||||||
|
README.rst
|
||||||
|
setup.cfg
|
||||||
|
setup.py
|
||||||
|
docs/Makefile
|
||||||
|
docs/api-stability.rst
|
||||||
|
docs/changelog.rst
|
||||||
|
docs/community.rst
|
||||||
|
docs/conf.py
|
||||||
|
docs/cryptography-docs.py
|
||||||
|
docs/doing-a-release.rst
|
||||||
|
docs/exceptions.rst
|
||||||
|
docs/faq.rst
|
||||||
|
docs/fernet.rst
|
||||||
|
docs/glossary.rst
|
||||||
|
docs/index.rst
|
||||||
|
docs/installation.rst
|
||||||
|
docs/limitations.rst
|
||||||
|
docs/make.bat
|
||||||
|
docs/random-numbers.rst
|
||||||
|
docs/security.rst
|
||||||
|
docs/spelling_wordlist.txt
|
||||||
|
docs/_static/.keep
|
||||||
|
docs/development/c-bindings.rst
|
||||||
|
docs/development/getting-started.rst
|
||||||
|
docs/development/index.rst
|
||||||
|
docs/development/reviewing-patches.rst
|
||||||
|
docs/development/submitting-patches.rst
|
||||||
|
docs/development/test-vectors.rst
|
||||||
|
docs/development/custom-vectors/cast5.rst
|
||||||
|
docs/development/custom-vectors/idea.rst
|
||||||
|
docs/development/custom-vectors/secp256k1.rst
|
||||||
|
docs/development/custom-vectors/seed.rst
|
||||||
|
docs/development/custom-vectors/cast5/generate_cast5.py
|
||||||
|
docs/development/custom-vectors/cast5/verify_cast5.go
|
||||||
|
docs/development/custom-vectors/idea/generate_idea.py
|
||||||
|
docs/development/custom-vectors/idea/verify_idea.py
|
||||||
|
docs/development/custom-vectors/secp256k1/generate_secp256k1.py
|
||||||
|
docs/development/custom-vectors/secp256k1/verify_secp256k1.py
|
||||||
|
docs/development/custom-vectors/seed/generate_seed.py
|
||||||
|
docs/development/custom-vectors/seed/verify_seed.py
|
||||||
|
docs/hazmat/backends/commoncrypto.rst
|
||||||
|
docs/hazmat/backends/index.rst
|
||||||
|
docs/hazmat/backends/interfaces.rst
|
||||||
|
docs/hazmat/backends/multibackend.rst
|
||||||
|
docs/hazmat/backends/openssl.rst
|
||||||
|
docs/hazmat/bindings/commoncrypto.rst
|
||||||
|
docs/hazmat/bindings/index.rst
|
||||||
|
docs/hazmat/bindings/openssl.rst
|
||||||
|
docs/hazmat/primitives/constant-time.rst
|
||||||
|
docs/hazmat/primitives/cryptographic-hashes.rst
|
||||||
|
docs/hazmat/primitives/index.rst
|
||||||
|
docs/hazmat/primitives/interfaces.rst
|
||||||
|
docs/hazmat/primitives/key-derivation-functions.rst
|
||||||
|
docs/hazmat/primitives/keywrap.rst
|
||||||
|
docs/hazmat/primitives/padding.rst
|
||||||
|
docs/hazmat/primitives/symmetric-encryption.rst
|
||||||
|
docs/hazmat/primitives/twofactor.rst
|
||||||
|
docs/hazmat/primitives/asymmetric/dh.rst
|
||||||
|
docs/hazmat/primitives/asymmetric/dsa.rst
|
||||||
|
docs/hazmat/primitives/asymmetric/ec.rst
|
||||||
|
docs/hazmat/primitives/asymmetric/index.rst
|
||||||
|
docs/hazmat/primitives/asymmetric/interfaces.rst
|
||||||
|
docs/hazmat/primitives/asymmetric/rsa.rst
|
||||||
|
docs/hazmat/primitives/asymmetric/serialization.rst
|
||||||
|
docs/hazmat/primitives/asymmetric/utils.rst
|
||||||
|
docs/hazmat/primitives/mac/cmac.rst
|
||||||
|
docs/hazmat/primitives/mac/hmac.rst
|
||||||
|
docs/hazmat/primitives/mac/index.rst
|
||||||
|
docs/x509/index.rst
|
||||||
|
docs/x509/reference.rst
|
||||||
|
docs/x509/tutorial.rst
|
||||||
|
src/_cffi_src/__init__.py
|
||||||
|
src/_cffi_src/build_commoncrypto.py
|
||||||
|
src/_cffi_src/build_constant_time.py
|
||||||
|
src/_cffi_src/build_openssl.py
|
||||||
|
src/_cffi_src/build_padding.py
|
||||||
|
src/_cffi_src/utils.py
|
||||||
|
src/_cffi_src/commoncrypto/__init__.py
|
||||||
|
src/_cffi_src/commoncrypto/cf.py
|
||||||
|
src/_cffi_src/commoncrypto/common_cryptor.py
|
||||||
|
src/_cffi_src/commoncrypto/common_digest.py
|
||||||
|
src/_cffi_src/commoncrypto/common_hmac.py
|
||||||
|
src/_cffi_src/commoncrypto/common_key_derivation.py
|
||||||
|
src/_cffi_src/commoncrypto/common_symmetric_key_wrap.py
|
||||||
|
src/_cffi_src/commoncrypto/secimport.py
|
||||||
|
src/_cffi_src/commoncrypto/secitem.py
|
||||||
|
src/_cffi_src/commoncrypto/seckey.py
|
||||||
|
src/_cffi_src/commoncrypto/seckeychain.py
|
||||||
|
src/_cffi_src/commoncrypto/sectransform.py
|
||||||
|
src/_cffi_src/hazmat_src/constant_time.c
|
||||||
|
src/_cffi_src/hazmat_src/constant_time.h
|
||||||
|
src/_cffi_src/hazmat_src/padding.c
|
||||||
|
src/_cffi_src/hazmat_src/padding.h
|
||||||
|
src/_cffi_src/openssl/__init__.py
|
||||||
|
src/_cffi_src/openssl/aes.py
|
||||||
|
src/_cffi_src/openssl/asn1.py
|
||||||
|
src/_cffi_src/openssl/bignum.py
|
||||||
|
src/_cffi_src/openssl/bio.py
|
||||||
|
src/_cffi_src/openssl/cmac.py
|
||||||
|
src/_cffi_src/openssl/cms.py
|
||||||
|
src/_cffi_src/openssl/conf.py
|
||||||
|
src/_cffi_src/openssl/crypto.py
|
||||||
|
src/_cffi_src/openssl/dh.py
|
||||||
|
src/_cffi_src/openssl/dsa.py
|
||||||
|
src/_cffi_src/openssl/ec.py
|
||||||
|
src/_cffi_src/openssl/ecdh.py
|
||||||
|
src/_cffi_src/openssl/ecdsa.py
|
||||||
|
src/_cffi_src/openssl/engine.py
|
||||||
|
src/_cffi_src/openssl/err.py
|
||||||
|
src/_cffi_src/openssl/evp.py
|
||||||
|
src/_cffi_src/openssl/hmac.py
|
||||||
|
src/_cffi_src/openssl/nid.py
|
||||||
|
src/_cffi_src/openssl/objects.py
|
||||||
|
src/_cffi_src/openssl/opensslv.py
|
||||||
|
src/_cffi_src/openssl/pem.py
|
||||||
|
src/_cffi_src/openssl/pkcs12.py
|
||||||
|
src/_cffi_src/openssl/pkcs7.py
|
||||||
|
src/_cffi_src/openssl/rand.py
|
||||||
|
src/_cffi_src/openssl/rsa.py
|
||||||
|
src/_cffi_src/openssl/ssl.py
|
||||||
|
src/_cffi_src/openssl/x509.py
|
||||||
|
src/_cffi_src/openssl/x509_vfy.py
|
||||||
|
src/_cffi_src/openssl/x509name.py
|
||||||
|
src/_cffi_src/openssl/x509v3.py
|
||||||
|
src/cryptography/__about__.py
|
||||||
|
src/cryptography/__init__.py
|
||||||
|
src/cryptography/exceptions.py
|
||||||
|
src/cryptography/fernet.py
|
||||||
|
src/cryptography/utils.py
|
||||||
|
src/cryptography.egg-info/PKG-INFO
|
||||||
|
src/cryptography.egg-info/SOURCES.txt
|
||||||
|
src/cryptography.egg-info/dependency_links.txt
|
||||||
|
src/cryptography.egg-info/entry_points.txt
|
||||||
|
src/cryptography.egg-info/not-zip-safe
|
||||||
|
src/cryptography.egg-info/requires.txt
|
||||||
|
src/cryptography.egg-info/top_level.txt
|
||||||
|
src/cryptography/hazmat/__init__.py
|
||||||
|
src/cryptography/hazmat/backends/__init__.py
|
||||||
|
src/cryptography/hazmat/backends/interfaces.py
|
||||||
|
src/cryptography/hazmat/backends/multibackend.py
|
||||||
|
src/cryptography/hazmat/backends/commoncrypto/__init__.py
|
||||||
|
src/cryptography/hazmat/backends/commoncrypto/backend.py
|
||||||
|
src/cryptography/hazmat/backends/commoncrypto/ciphers.py
|
||||||
|
src/cryptography/hazmat/backends/commoncrypto/hashes.py
|
||||||
|
src/cryptography/hazmat/backends/commoncrypto/hmac.py
|
||||||
|
src/cryptography/hazmat/backends/openssl/__init__.py
|
||||||
|
src/cryptography/hazmat/backends/openssl/backend.py
|
||||||
|
src/cryptography/hazmat/backends/openssl/ciphers.py
|
||||||
|
src/cryptography/hazmat/backends/openssl/cmac.py
|
||||||
|
src/cryptography/hazmat/backends/openssl/dsa.py
|
||||||
|
src/cryptography/hazmat/backends/openssl/ec.py
|
||||||
|
src/cryptography/hazmat/backends/openssl/hashes.py
|
||||||
|
src/cryptography/hazmat/backends/openssl/hmac.py
|
||||||
|
src/cryptography/hazmat/backends/openssl/rsa.py
|
||||||
|
src/cryptography/hazmat/backends/openssl/utils.py
|
||||||
|
src/cryptography/hazmat/backends/openssl/x509.py
|
||||||
|
src/cryptography/hazmat/bindings/__init__.py
|
||||||
|
src/cryptography/hazmat/bindings/commoncrypto/__init__.py
|
||||||
|
src/cryptography/hazmat/bindings/commoncrypto/binding.py
|
||||||
|
src/cryptography/hazmat/bindings/openssl/__init__.py
|
||||||
|
src/cryptography/hazmat/bindings/openssl/_conditional.py
|
||||||
|
src/cryptography/hazmat/bindings/openssl/binding.py
|
||||||
|
src/cryptography/hazmat/primitives/__init__.py
|
||||||
|
src/cryptography/hazmat/primitives/cmac.py
|
||||||
|
src/cryptography/hazmat/primitives/constant_time.py
|
||||||
|
src/cryptography/hazmat/primitives/hashes.py
|
||||||
|
src/cryptography/hazmat/primitives/hmac.py
|
||||||
|
src/cryptography/hazmat/primitives/keywrap.py
|
||||||
|
src/cryptography/hazmat/primitives/padding.py
|
||||||
|
src/cryptography/hazmat/primitives/serialization.py
|
||||||
|
src/cryptography/hazmat/primitives/asymmetric/__init__.py
|
||||||
|
src/cryptography/hazmat/primitives/asymmetric/dh.py
|
||||||
|
src/cryptography/hazmat/primitives/asymmetric/dsa.py
|
||||||
|
src/cryptography/hazmat/primitives/asymmetric/ec.py
|
||||||
|
src/cryptography/hazmat/primitives/asymmetric/padding.py
|
||||||
|
src/cryptography/hazmat/primitives/asymmetric/rsa.py
|
||||||
|
src/cryptography/hazmat/primitives/asymmetric/utils.py
|
||||||
|
src/cryptography/hazmat/primitives/ciphers/__init__.py
|
||||||
|
src/cryptography/hazmat/primitives/ciphers/algorithms.py
|
||||||
|
src/cryptography/hazmat/primitives/ciphers/base.py
|
||||||
|
src/cryptography/hazmat/primitives/ciphers/modes.py
|
||||||
|
src/cryptography/hazmat/primitives/interfaces/__init__.py
|
||||||
|
src/cryptography/hazmat/primitives/kdf/__init__.py
|
||||||
|
src/cryptography/hazmat/primitives/kdf/concatkdf.py
|
||||||
|
src/cryptography/hazmat/primitives/kdf/hkdf.py
|
||||||
|
src/cryptography/hazmat/primitives/kdf/pbkdf2.py
|
||||||
|
src/cryptography/hazmat/primitives/kdf/x963kdf.py
|
||||||
|
src/cryptography/hazmat/primitives/twofactor/__init__.py
|
||||||
|
src/cryptography/hazmat/primitives/twofactor/hotp.py
|
||||||
|
src/cryptography/hazmat/primitives/twofactor/totp.py
|
||||||
|
src/cryptography/hazmat/primitives/twofactor/utils.py
|
||||||
|
src/cryptography/x509/__init__.py
|
||||||
|
src/cryptography/x509/base.py
|
||||||
|
src/cryptography/x509/extensions.py
|
||||||
|
src/cryptography/x509/general_name.py
|
||||||
|
src/cryptography/x509/name.py
|
||||||
|
src/cryptography/x509/oid.py
|
||||||
|
tests/__init__.py
|
||||||
|
tests/conftest.py
|
||||||
|
tests/test_fernet.py
|
||||||
|
tests/test_interfaces.py
|
||||||
|
tests/test_utils.py
|
||||||
|
tests/test_warnings.py
|
||||||
|
tests/test_x509.py
|
||||||
|
tests/test_x509_ext.py
|
||||||
|
tests/utils.py
|
||||||
|
tests/hazmat/__init__.py
|
||||||
|
tests/hazmat/backends/__init__.py
|
||||||
|
tests/hazmat/backends/test_commoncrypto.py
|
||||||
|
tests/hazmat/backends/test_multibackend.py
|
||||||
|
tests/hazmat/backends/test_openssl.py
|
||||||
|
tests/hazmat/bindings/test_commoncrypto.py
|
||||||
|
tests/hazmat/bindings/test_openssl.py
|
||||||
|
tests/hazmat/primitives/__init__.py
|
||||||
|
tests/hazmat/primitives/fixtures_dsa.py
|
||||||
|
tests/hazmat/primitives/fixtures_rsa.py
|
||||||
|
tests/hazmat/primitives/test_3des.py
|
||||||
|
tests/hazmat/primitives/test_aes.py
|
||||||
|
tests/hazmat/primitives/test_arc4.py
|
||||||
|
tests/hazmat/primitives/test_asym_utils.py
|
||||||
|
tests/hazmat/primitives/test_block.py
|
||||||
|
tests/hazmat/primitives/test_blowfish.py
|
||||||
|
tests/hazmat/primitives/test_camellia.py
|
||||||
|
tests/hazmat/primitives/test_cast5.py
|
||||||
|
tests/hazmat/primitives/test_ciphers.py
|
||||||
|
tests/hazmat/primitives/test_cmac.py
|
||||||
|
tests/hazmat/primitives/test_concatkdf.py
|
||||||
|
tests/hazmat/primitives/test_constant_time.py
|
||||||
|
tests/hazmat/primitives/test_dh.py
|
||||||
|
tests/hazmat/primitives/test_dsa.py
|
||||||
|
tests/hazmat/primitives/test_ec.py
|
||||||
|
tests/hazmat/primitives/test_hash_vectors.py
|
||||||
|
tests/hazmat/primitives/test_hashes.py
|
||||||
|
tests/hazmat/primitives/test_hkdf.py
|
||||||
|
tests/hazmat/primitives/test_hkdf_vectors.py
|
||||||
|
tests/hazmat/primitives/test_hmac.py
|
||||||
|
tests/hazmat/primitives/test_hmac_vectors.py
|
||||||
|
tests/hazmat/primitives/test_idea.py
|
||||||
|
tests/hazmat/primitives/test_keywrap.py
|
||||||
|
tests/hazmat/primitives/test_padding.py
|
||||||
|
tests/hazmat/primitives/test_pbkdf2hmac.py
|
||||||
|
tests/hazmat/primitives/test_pbkdf2hmac_vectors.py
|
||||||
|
tests/hazmat/primitives/test_rsa.py
|
||||||
|
tests/hazmat/primitives/test_seed.py
|
||||||
|
tests/hazmat/primitives/test_serialization.py
|
||||||
|
tests/hazmat/primitives/test_x963_vectors.py
|
||||||
|
tests/hazmat/primitives/test_x963kdf.py
|
||||||
|
tests/hazmat/primitives/utils.py
|
||||||
|
tests/hazmat/primitives/twofactor/__init__.py
|
||||||
|
tests/hazmat/primitives/twofactor/test_hotp.py
|
||||||
|
tests/hazmat/primitives/twofactor/test_totp.py
|
||||||
|
tests/hypothesis/__init__.py
|
||||||
|
tests/hypothesis/test_fernet.py
|
|
@ -1,202 +1,143 @@
|
||||||
../cryptography/utils.py
|
|
||||||
../cryptography/__about__.py
|
../cryptography/__about__.py
|
||||||
../cryptography/__init__.py
|
../cryptography/__init__.py
|
||||||
../cryptography/exceptions.py
|
../cryptography/exceptions.py
|
||||||
../cryptography/fernet.py
|
../cryptography/fernet.py
|
||||||
|
../cryptography/utils.py
|
||||||
../cryptography/hazmat/__init__.py
|
../cryptography/hazmat/__init__.py
|
||||||
../cryptography/hazmat/bindings/utils.py
|
../cryptography/x509/__init__.py
|
||||||
../cryptography/hazmat/bindings/__init__.py
|
../cryptography/x509/base.py
|
||||||
../cryptography/hazmat/primitives/interfaces.py
|
../cryptography/x509/extensions.py
|
||||||
../cryptography/hazmat/primitives/constant_time.py
|
../cryptography/x509/general_name.py
|
||||||
../cryptography/hazmat/primitives/__init__.py
|
../cryptography/x509/name.py
|
||||||
../cryptography/hazmat/primitives/hashes.py
|
../cryptography/x509/oid.py
|
||||||
../cryptography/hazmat/primitives/hmac.py
|
../cryptography/hazmat/backends/__init__.py
|
||||||
../cryptography/hazmat/primitives/padding.py
|
|
||||||
../cryptography/hazmat/primitives/serialization.py
|
|
||||||
../cryptography/hazmat/primitives/cmac.py
|
|
||||||
../cryptography/hazmat/backends/interfaces.py
|
../cryptography/hazmat/backends/interfaces.py
|
||||||
../cryptography/hazmat/backends/multibackend.py
|
../cryptography/hazmat/backends/multibackend.py
|
||||||
../cryptography/hazmat/backends/__init__.py
|
../cryptography/hazmat/bindings/__init__.py
|
||||||
../cryptography/hazmat/bindings/commoncrypto/secimport.py
|
../cryptography/hazmat/primitives/__init__.py
|
||||||
../cryptography/hazmat/bindings/commoncrypto/common_cryptor.py
|
../cryptography/hazmat/primitives/cmac.py
|
||||||
../cryptography/hazmat/bindings/commoncrypto/seckeychain.py
|
../cryptography/hazmat/primitives/constant_time.py
|
||||||
../cryptography/hazmat/bindings/commoncrypto/common_hmac.py
|
../cryptography/hazmat/primitives/hashes.py
|
||||||
../cryptography/hazmat/bindings/commoncrypto/__init__.py
|
../cryptography/hazmat/primitives/hmac.py
|
||||||
../cryptography/hazmat/bindings/commoncrypto/common_key_derivation.py
|
../cryptography/hazmat/primitives/keywrap.py
|
||||||
../cryptography/hazmat/bindings/commoncrypto/sectransform.py
|
../cryptography/hazmat/primitives/padding.py
|
||||||
../cryptography/hazmat/bindings/commoncrypto/binding.py
|
../cryptography/hazmat/primitives/serialization.py
|
||||||
../cryptography/hazmat/bindings/commoncrypto/common_digest.py
|
|
||||||
../cryptography/hazmat/bindings/commoncrypto/seckey.py
|
|
||||||
../cryptography/hazmat/bindings/commoncrypto/secitem.py
|
|
||||||
../cryptography/hazmat/bindings/commoncrypto/cf.py
|
|
||||||
../cryptography/hazmat/bindings/openssl/opensslv.py
|
|
||||||
../cryptography/hazmat/bindings/openssl/ec.py
|
|
||||||
../cryptography/hazmat/bindings/openssl/x509_vfy.py
|
|
||||||
../cryptography/hazmat/bindings/openssl/aes.py
|
|
||||||
../cryptography/hazmat/bindings/openssl/asn1.py
|
|
||||||
../cryptography/hazmat/bindings/openssl/objects.py
|
|
||||||
../cryptography/hazmat/bindings/openssl/dsa.py
|
|
||||||
../cryptography/hazmat/bindings/openssl/x509name.py
|
|
||||||
../cryptography/hazmat/bindings/openssl/osrandom_engine.py
|
|
||||||
../cryptography/hazmat/bindings/openssl/rand.py
|
|
||||||
../cryptography/hazmat/bindings/openssl/cms.py
|
|
||||||
../cryptography/hazmat/bindings/openssl/engine.py
|
|
||||||
../cryptography/hazmat/bindings/openssl/__init__.py
|
|
||||||
../cryptography/hazmat/bindings/openssl/ssl.py
|
|
||||||
../cryptography/hazmat/bindings/openssl/nid.py
|
|
||||||
../cryptography/hazmat/bindings/openssl/x509v3.py
|
|
||||||
../cryptography/hazmat/bindings/openssl/err.py
|
|
||||||
../cryptography/hazmat/bindings/openssl/bio.py
|
|
||||||
../cryptography/hazmat/bindings/openssl/ecdsa.py
|
|
||||||
../cryptography/hazmat/bindings/openssl/pkcs7.py
|
|
||||||
../cryptography/hazmat/bindings/openssl/bignum.py
|
|
||||||
../cryptography/hazmat/bindings/openssl/binding.py
|
|
||||||
../cryptography/hazmat/bindings/openssl/pem.py
|
|
||||||
../cryptography/hazmat/bindings/openssl/rsa.py
|
|
||||||
../cryptography/hazmat/bindings/openssl/hmac.py
|
|
||||||
../cryptography/hazmat/bindings/openssl/conf.py
|
|
||||||
../cryptography/hazmat/bindings/openssl/dh.py
|
|
||||||
../cryptography/hazmat/bindings/openssl/x509.py
|
|
||||||
../cryptography/hazmat/bindings/openssl/ecdh.py
|
|
||||||
../cryptography/hazmat/bindings/openssl/evp.py
|
|
||||||
../cryptography/hazmat/bindings/openssl/cmac.py
|
|
||||||
../cryptography/hazmat/bindings/openssl/crypto.py
|
|
||||||
../cryptography/hazmat/bindings/openssl/pkcs12.py
|
|
||||||
../cryptography/hazmat/primitives/kdf/__init__.py
|
|
||||||
../cryptography/hazmat/primitives/kdf/hkdf.py
|
|
||||||
../cryptography/hazmat/primitives/kdf/pbkdf2.py
|
|
||||||
../cryptography/hazmat/primitives/asymmetric/ec.py
|
|
||||||
../cryptography/hazmat/primitives/asymmetric/dsa.py
|
|
||||||
../cryptography/hazmat/primitives/asymmetric/__init__.py
|
|
||||||
../cryptography/hazmat/primitives/asymmetric/rsa.py
|
|
||||||
../cryptography/hazmat/primitives/asymmetric/padding.py
|
|
||||||
../cryptography/hazmat/primitives/ciphers/base.py
|
|
||||||
../cryptography/hazmat/primitives/ciphers/__init__.py
|
|
||||||
../cryptography/hazmat/primitives/ciphers/modes.py
|
|
||||||
../cryptography/hazmat/primitives/ciphers/algorithms.py
|
|
||||||
../cryptography/hazmat/primitives/twofactor/__init__.py
|
|
||||||
../cryptography/hazmat/primitives/twofactor/totp.py
|
|
||||||
../cryptography/hazmat/primitives/twofactor/hotp.py
|
|
||||||
../cryptography/hazmat/backends/commoncrypto/backend.py
|
|
||||||
../cryptography/hazmat/backends/commoncrypto/__init__.py
|
../cryptography/hazmat/backends/commoncrypto/__init__.py
|
||||||
|
../cryptography/hazmat/backends/commoncrypto/backend.py
|
||||||
|
../cryptography/hazmat/backends/commoncrypto/ciphers.py
|
||||||
../cryptography/hazmat/backends/commoncrypto/hashes.py
|
../cryptography/hazmat/backends/commoncrypto/hashes.py
|
||||||
../cryptography/hazmat/backends/commoncrypto/hmac.py
|
../cryptography/hazmat/backends/commoncrypto/hmac.py
|
||||||
../cryptography/hazmat/backends/commoncrypto/ciphers.py
|
|
||||||
../cryptography/hazmat/backends/openssl/ec.py
|
|
||||||
../cryptography/hazmat/backends/openssl/dsa.py
|
|
||||||
../cryptography/hazmat/backends/openssl/backend.py
|
|
||||||
../cryptography/hazmat/backends/openssl/__init__.py
|
../cryptography/hazmat/backends/openssl/__init__.py
|
||||||
../cryptography/hazmat/backends/openssl/hashes.py
|
../cryptography/hazmat/backends/openssl/backend.py
|
||||||
../cryptography/hazmat/backends/openssl/rsa.py
|
|
||||||
../cryptography/hazmat/backends/openssl/hmac.py
|
|
||||||
../cryptography/hazmat/backends/openssl/cmac.py
|
|
||||||
../cryptography/hazmat/backends/openssl/ciphers.py
|
../cryptography/hazmat/backends/openssl/ciphers.py
|
||||||
../cryptography/hazmat/bindings/__pycache__/_Cryptography_cffi_3e31f141x4000d087.c
|
../cryptography/hazmat/backends/openssl/cmac.py
|
||||||
../cryptography/hazmat/primitives/__pycache__/_Cryptography_cffi_7ab3712bx4f158fee.c
|
../cryptography/hazmat/backends/openssl/dsa.py
|
||||||
../cryptography/hazmat/primitives/__pycache__/_Cryptography_cffi_dd416c1exc1767c5a.c
|
../cryptography/hazmat/backends/openssl/ec.py
|
||||||
../cryptography/hazmat/primitives/src/constant_time.c
|
../cryptography/hazmat/backends/openssl/hashes.py
|
||||||
../cryptography/hazmat/primitives/src/constant_time.h
|
../cryptography/hazmat/backends/openssl/hmac.py
|
||||||
../cryptography/__pycache__/utils.cpython-34.pyc
|
../cryptography/hazmat/backends/openssl/rsa.py
|
||||||
|
../cryptography/hazmat/backends/openssl/utils.py
|
||||||
|
../cryptography/hazmat/backends/openssl/x509.py
|
||||||
|
../cryptography/hazmat/bindings/commoncrypto/__init__.py
|
||||||
|
../cryptography/hazmat/bindings/commoncrypto/binding.py
|
||||||
|
../cryptography/hazmat/bindings/openssl/__init__.py
|
||||||
|
../cryptography/hazmat/bindings/openssl/_conditional.py
|
||||||
|
../cryptography/hazmat/bindings/openssl/binding.py
|
||||||
|
../cryptography/hazmat/primitives/asymmetric/__init__.py
|
||||||
|
../cryptography/hazmat/primitives/asymmetric/dh.py
|
||||||
|
../cryptography/hazmat/primitives/asymmetric/dsa.py
|
||||||
|
../cryptography/hazmat/primitives/asymmetric/ec.py
|
||||||
|
../cryptography/hazmat/primitives/asymmetric/padding.py
|
||||||
|
../cryptography/hazmat/primitives/asymmetric/rsa.py
|
||||||
|
../cryptography/hazmat/primitives/asymmetric/utils.py
|
||||||
|
../cryptography/hazmat/primitives/ciphers/__init__.py
|
||||||
|
../cryptography/hazmat/primitives/ciphers/algorithms.py
|
||||||
|
../cryptography/hazmat/primitives/ciphers/base.py
|
||||||
|
../cryptography/hazmat/primitives/ciphers/modes.py
|
||||||
|
../cryptography/hazmat/primitives/interfaces/__init__.py
|
||||||
|
../cryptography/hazmat/primitives/kdf/__init__.py
|
||||||
|
../cryptography/hazmat/primitives/kdf/concatkdf.py
|
||||||
|
../cryptography/hazmat/primitives/kdf/hkdf.py
|
||||||
|
../cryptography/hazmat/primitives/kdf/pbkdf2.py
|
||||||
|
../cryptography/hazmat/primitives/kdf/x963kdf.py
|
||||||
|
../cryptography/hazmat/primitives/twofactor/__init__.py
|
||||||
|
../cryptography/hazmat/primitives/twofactor/hotp.py
|
||||||
|
../cryptography/hazmat/primitives/twofactor/totp.py
|
||||||
|
../cryptography/hazmat/primitives/twofactor/utils.py
|
||||||
../cryptography/__pycache__/__about__.cpython-34.pyc
|
../cryptography/__pycache__/__about__.cpython-34.pyc
|
||||||
../cryptography/__pycache__/__init__.cpython-34.pyc
|
../cryptography/__pycache__/__init__.cpython-34.pyc
|
||||||
../cryptography/__pycache__/exceptions.cpython-34.pyc
|
../cryptography/__pycache__/exceptions.cpython-34.pyc
|
||||||
../cryptography/__pycache__/fernet.cpython-34.pyc
|
../cryptography/__pycache__/fernet.cpython-34.pyc
|
||||||
|
../cryptography/__pycache__/utils.cpython-34.pyc
|
||||||
../cryptography/hazmat/__pycache__/__init__.cpython-34.pyc
|
../cryptography/hazmat/__pycache__/__init__.cpython-34.pyc
|
||||||
../cryptography/hazmat/bindings/__pycache__/utils.cpython-34.pyc
|
../cryptography/x509/__pycache__/__init__.cpython-34.pyc
|
||||||
../cryptography/hazmat/bindings/__pycache__/__init__.cpython-34.pyc
|
../cryptography/x509/__pycache__/base.cpython-34.pyc
|
||||||
../cryptography/hazmat/primitives/__pycache__/interfaces.cpython-34.pyc
|
../cryptography/x509/__pycache__/extensions.cpython-34.pyc
|
||||||
../cryptography/hazmat/primitives/__pycache__/constant_time.cpython-34.pyc
|
../cryptography/x509/__pycache__/general_name.cpython-34.pyc
|
||||||
../cryptography/hazmat/primitives/__pycache__/__init__.cpython-34.pyc
|
../cryptography/x509/__pycache__/name.cpython-34.pyc
|
||||||
../cryptography/hazmat/primitives/__pycache__/hashes.cpython-34.pyc
|
../cryptography/x509/__pycache__/oid.cpython-34.pyc
|
||||||
../cryptography/hazmat/primitives/__pycache__/hmac.cpython-34.pyc
|
../cryptography/hazmat/backends/__pycache__/__init__.cpython-34.pyc
|
||||||
../cryptography/hazmat/primitives/__pycache__/padding.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/primitives/__pycache__/serialization.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/primitives/__pycache__/cmac.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/backends/__pycache__/interfaces.cpython-34.pyc
|
../cryptography/hazmat/backends/__pycache__/interfaces.cpython-34.pyc
|
||||||
../cryptography/hazmat/backends/__pycache__/multibackend.cpython-34.pyc
|
../cryptography/hazmat/backends/__pycache__/multibackend.cpython-34.pyc
|
||||||
../cryptography/hazmat/backends/__pycache__/__init__.cpython-34.pyc
|
../cryptography/hazmat/bindings/__pycache__/__init__.cpython-34.pyc
|
||||||
../cryptography/hazmat/bindings/commoncrypto/__pycache__/secimport.cpython-34.pyc
|
../cryptography/hazmat/primitives/__pycache__/__init__.cpython-34.pyc
|
||||||
../cryptography/hazmat/bindings/commoncrypto/__pycache__/common_cryptor.cpython-34.pyc
|
../cryptography/hazmat/primitives/__pycache__/cmac.cpython-34.pyc
|
||||||
../cryptography/hazmat/bindings/commoncrypto/__pycache__/seckeychain.cpython-34.pyc
|
../cryptography/hazmat/primitives/__pycache__/constant_time.cpython-34.pyc
|
||||||
../cryptography/hazmat/bindings/commoncrypto/__pycache__/common_hmac.cpython-34.pyc
|
../cryptography/hazmat/primitives/__pycache__/hashes.cpython-34.pyc
|
||||||
../cryptography/hazmat/bindings/commoncrypto/__pycache__/__init__.cpython-34.pyc
|
../cryptography/hazmat/primitives/__pycache__/hmac.cpython-34.pyc
|
||||||
../cryptography/hazmat/bindings/commoncrypto/__pycache__/common_key_derivation.cpython-34.pyc
|
../cryptography/hazmat/primitives/__pycache__/keywrap.cpython-34.pyc
|
||||||
../cryptography/hazmat/bindings/commoncrypto/__pycache__/sectransform.cpython-34.pyc
|
../cryptography/hazmat/primitives/__pycache__/padding.cpython-34.pyc
|
||||||
../cryptography/hazmat/bindings/commoncrypto/__pycache__/binding.cpython-34.pyc
|
../cryptography/hazmat/primitives/__pycache__/serialization.cpython-34.pyc
|
||||||
../cryptography/hazmat/bindings/commoncrypto/__pycache__/common_digest.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/bindings/commoncrypto/__pycache__/seckey.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/bindings/commoncrypto/__pycache__/secitem.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/bindings/commoncrypto/__pycache__/cf.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/bindings/openssl/__pycache__/opensslv.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/bindings/openssl/__pycache__/ec.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/bindings/openssl/__pycache__/x509_vfy.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/bindings/openssl/__pycache__/aes.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/bindings/openssl/__pycache__/asn1.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/bindings/openssl/__pycache__/objects.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/bindings/openssl/__pycache__/dsa.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/bindings/openssl/__pycache__/x509name.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/bindings/openssl/__pycache__/osrandom_engine.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/bindings/openssl/__pycache__/rand.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/bindings/openssl/__pycache__/cms.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/bindings/openssl/__pycache__/engine.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/bindings/openssl/__pycache__/__init__.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/bindings/openssl/__pycache__/ssl.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/bindings/openssl/__pycache__/nid.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/bindings/openssl/__pycache__/x509v3.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/bindings/openssl/__pycache__/err.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/bindings/openssl/__pycache__/bio.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/bindings/openssl/__pycache__/ecdsa.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/bindings/openssl/__pycache__/pkcs7.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/bindings/openssl/__pycache__/bignum.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/bindings/openssl/__pycache__/binding.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/bindings/openssl/__pycache__/pem.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/bindings/openssl/__pycache__/rsa.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/bindings/openssl/__pycache__/hmac.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/bindings/openssl/__pycache__/conf.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/bindings/openssl/__pycache__/dh.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/bindings/openssl/__pycache__/x509.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/bindings/openssl/__pycache__/ecdh.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/bindings/openssl/__pycache__/evp.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/bindings/openssl/__pycache__/cmac.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/bindings/openssl/__pycache__/crypto.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/bindings/openssl/__pycache__/pkcs12.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/primitives/kdf/__pycache__/__init__.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/primitives/kdf/__pycache__/hkdf.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/primitives/kdf/__pycache__/pbkdf2.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/primitives/asymmetric/__pycache__/ec.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/primitives/asymmetric/__pycache__/dsa.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/primitives/asymmetric/__pycache__/__init__.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/primitives/asymmetric/__pycache__/rsa.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/primitives/asymmetric/__pycache__/padding.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/primitives/ciphers/__pycache__/base.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/primitives/ciphers/__pycache__/__init__.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/primitives/ciphers/__pycache__/modes.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/primitives/ciphers/__pycache__/algorithms.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/primitives/twofactor/__pycache__/__init__.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/primitives/twofactor/__pycache__/totp.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/primitives/twofactor/__pycache__/hotp.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/backends/commoncrypto/__pycache__/backend.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/backends/commoncrypto/__pycache__/__init__.cpython-34.pyc
|
../cryptography/hazmat/backends/commoncrypto/__pycache__/__init__.cpython-34.pyc
|
||||||
|
../cryptography/hazmat/backends/commoncrypto/__pycache__/backend.cpython-34.pyc
|
||||||
|
../cryptography/hazmat/backends/commoncrypto/__pycache__/ciphers.cpython-34.pyc
|
||||||
../cryptography/hazmat/backends/commoncrypto/__pycache__/hashes.cpython-34.pyc
|
../cryptography/hazmat/backends/commoncrypto/__pycache__/hashes.cpython-34.pyc
|
||||||
../cryptography/hazmat/backends/commoncrypto/__pycache__/hmac.cpython-34.pyc
|
../cryptography/hazmat/backends/commoncrypto/__pycache__/hmac.cpython-34.pyc
|
||||||
../cryptography/hazmat/backends/commoncrypto/__pycache__/ciphers.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/backends/openssl/__pycache__/ec.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/backends/openssl/__pycache__/dsa.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/backends/openssl/__pycache__/backend.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/backends/openssl/__pycache__/__init__.cpython-34.pyc
|
../cryptography/hazmat/backends/openssl/__pycache__/__init__.cpython-34.pyc
|
||||||
../cryptography/hazmat/backends/openssl/__pycache__/hashes.cpython-34.pyc
|
../cryptography/hazmat/backends/openssl/__pycache__/backend.cpython-34.pyc
|
||||||
../cryptography/hazmat/backends/openssl/__pycache__/rsa.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/backends/openssl/__pycache__/hmac.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/backends/openssl/__pycache__/cmac.cpython-34.pyc
|
|
||||||
../cryptography/hazmat/backends/openssl/__pycache__/ciphers.cpython-34.pyc
|
../cryptography/hazmat/backends/openssl/__pycache__/ciphers.cpython-34.pyc
|
||||||
../cryptography/_Cryptography_cffi_3e31f141x4000d087.cpython-34m.so
|
../cryptography/hazmat/backends/openssl/__pycache__/cmac.cpython-34.pyc
|
||||||
../cryptography/_Cryptography_cffi_7ab3712bx4f158fee.cpython-34m.so
|
../cryptography/hazmat/backends/openssl/__pycache__/dsa.cpython-34.pyc
|
||||||
../cryptography/_Cryptography_cffi_dd416c1exc1767c5a.cpython-34m.so
|
../cryptography/hazmat/backends/openssl/__pycache__/ec.cpython-34.pyc
|
||||||
|
../cryptography/hazmat/backends/openssl/__pycache__/hashes.cpython-34.pyc
|
||||||
|
../cryptography/hazmat/backends/openssl/__pycache__/hmac.cpython-34.pyc
|
||||||
|
../cryptography/hazmat/backends/openssl/__pycache__/rsa.cpython-34.pyc
|
||||||
|
../cryptography/hazmat/backends/openssl/__pycache__/utils.cpython-34.pyc
|
||||||
|
../cryptography/hazmat/backends/openssl/__pycache__/x509.cpython-34.pyc
|
||||||
|
../cryptography/hazmat/bindings/commoncrypto/__pycache__/__init__.cpython-34.pyc
|
||||||
|
../cryptography/hazmat/bindings/commoncrypto/__pycache__/binding.cpython-34.pyc
|
||||||
|
../cryptography/hazmat/bindings/openssl/__pycache__/__init__.cpython-34.pyc
|
||||||
|
../cryptography/hazmat/bindings/openssl/__pycache__/_conditional.cpython-34.pyc
|
||||||
|
../cryptography/hazmat/bindings/openssl/__pycache__/binding.cpython-34.pyc
|
||||||
|
../cryptography/hazmat/primitives/asymmetric/__pycache__/__init__.cpython-34.pyc
|
||||||
|
../cryptography/hazmat/primitives/asymmetric/__pycache__/dh.cpython-34.pyc
|
||||||
|
../cryptography/hazmat/primitives/asymmetric/__pycache__/dsa.cpython-34.pyc
|
||||||
|
../cryptography/hazmat/primitives/asymmetric/__pycache__/ec.cpython-34.pyc
|
||||||
|
../cryptography/hazmat/primitives/asymmetric/__pycache__/padding.cpython-34.pyc
|
||||||
|
../cryptography/hazmat/primitives/asymmetric/__pycache__/rsa.cpython-34.pyc
|
||||||
|
../cryptography/hazmat/primitives/asymmetric/__pycache__/utils.cpython-34.pyc
|
||||||
|
../cryptography/hazmat/primitives/ciphers/__pycache__/__init__.cpython-34.pyc
|
||||||
|
../cryptography/hazmat/primitives/ciphers/__pycache__/algorithms.cpython-34.pyc
|
||||||
|
../cryptography/hazmat/primitives/ciphers/__pycache__/base.cpython-34.pyc
|
||||||
|
../cryptography/hazmat/primitives/ciphers/__pycache__/modes.cpython-34.pyc
|
||||||
|
../cryptography/hazmat/primitives/interfaces/__pycache__/__init__.cpython-34.pyc
|
||||||
|
../cryptography/hazmat/primitives/kdf/__pycache__/__init__.cpython-34.pyc
|
||||||
|
../cryptography/hazmat/primitives/kdf/__pycache__/concatkdf.cpython-34.pyc
|
||||||
|
../cryptography/hazmat/primitives/kdf/__pycache__/hkdf.cpython-34.pyc
|
||||||
|
../cryptography/hazmat/primitives/kdf/__pycache__/pbkdf2.cpython-34.pyc
|
||||||
|
../cryptography/hazmat/primitives/kdf/__pycache__/x963kdf.cpython-34.pyc
|
||||||
|
../cryptography/hazmat/primitives/twofactor/__pycache__/__init__.cpython-34.pyc
|
||||||
|
../cryptography/hazmat/primitives/twofactor/__pycache__/hotp.cpython-34.pyc
|
||||||
|
../cryptography/hazmat/primitives/twofactor/__pycache__/totp.cpython-34.pyc
|
||||||
|
../cryptography/hazmat/primitives/twofactor/__pycache__/utils.cpython-34.pyc
|
||||||
|
../cryptography/hazmat/bindings/_openssl.cpython-34m.so
|
||||||
|
../cryptography/hazmat/bindings/_constant_time.cpython-34m.so
|
||||||
|
../cryptography/hazmat/bindings/_padding.cpython-34m.so
|
||||||
./
|
./
|
||||||
dependency_links.txt
|
dependency_links.txt
|
||||||
entry_points.txt
|
entry_points.txt
|
||||||
PKG-INFO
|
|
||||||
SOURCES.txt
|
|
||||||
not-zip-safe
|
not-zip-safe
|
||||||
top_level.txt
|
PKG-INFO
|
||||||
requires.txt
|
requires.txt
|
||||||
|
SOURCES.txt
|
||||||
|
top_level.txt
|
|
@ -0,0 +1,5 @@
|
||||||
|
idna>=2.0
|
||||||
|
pyasn1>=0.1.8
|
||||||
|
six>=1.4.1
|
||||||
|
setuptools
|
||||||
|
cffi>=1.1.0
|
|
@ -0,0 +1,4 @@
|
||||||
|
_constant_time
|
||||||
|
_openssl
|
||||||
|
_padding
|
||||||
|
cryptography
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,15 +1,7 @@
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# This file is dual licensed under the terms of the Apache License, Version
|
||||||
# you may not use this file except in compliance with the License.
|
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
|
||||||
# You may obtain a copy of the License at
|
# for complete details.
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
# implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
|
@ -22,10 +14,10 @@ __summary__ = ("cryptography is a package which provides cryptographic recipes"
|
||||||
" and primitives to Python developers.")
|
" and primitives to Python developers.")
|
||||||
__uri__ = "https://github.com/pyca/cryptography"
|
__uri__ = "https://github.com/pyca/cryptography"
|
||||||
|
|
||||||
__version__ = "0.6"
|
__version__ = "1.1"
|
||||||
|
|
||||||
__author__ = "The cryptography developers"
|
__author__ = "The cryptography developers"
|
||||||
__email__ = "cryptography-dev@python.org"
|
__email__ = "cryptography-dev@python.org"
|
||||||
|
|
||||||
__license__ = "Apache License, Version 2.0"
|
__license__ = "BSD or Apache License, Version 2.0"
|
||||||
__copyright__ = "Copyright 2013-2014 {0}".format(__author__)
|
__copyright__ = "Copyright 2013-2015 {0}".format(__author__)
|
||||||
|
|
|
@ -1,18 +1,12 @@
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# This file is dual licensed under the terms of the Apache License, Version
|
||||||
# you may not use this file except in compliance with the License.
|
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
|
||||||
# You may obtain a copy of the License at
|
# for complete details.
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
# implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import warnings
|
||||||
|
|
||||||
from cryptography.__about__ import (
|
from cryptography.__about__ import (
|
||||||
__author__, __copyright__, __email__, __license__, __summary__, __title__,
|
__author__, __copyright__, __email__, __license__, __summary__, __title__,
|
||||||
__uri__, __version__
|
__uri__, __version__
|
||||||
|
@ -23,3 +17,10 @@ __all__ = [
|
||||||
"__title__", "__summary__", "__uri__", "__version__", "__author__",
|
"__title__", "__summary__", "__uri__", "__version__", "__author__",
|
||||||
"__email__", "__license__", "__copyright__",
|
"__email__", "__license__", "__copyright__",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
if sys.version_info[:2] == (2, 6):
|
||||||
|
warnings.warn(
|
||||||
|
"Python 2.6 is no longer supported by the Python core team, please "
|
||||||
|
"upgrade your Python.",
|
||||||
|
DeprecationWarning
|
||||||
|
)
|
||||||
|
|
|
@ -1,28 +1,26 @@
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# This file is dual licensed under the terms of the Apache License, Version
|
||||||
# you may not use this file except in compliance with the License.
|
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
|
||||||
# You may obtain a copy of the License at
|
# for complete details.
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
# implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
class _Reasons(object):
|
from cryptography import utils
|
||||||
BACKEND_MISSING_INTERFACE = object()
|
from cryptography.hazmat.primitives import twofactor
|
||||||
UNSUPPORTED_HASH = object()
|
|
||||||
UNSUPPORTED_CIPHER = object()
|
|
||||||
UNSUPPORTED_PADDING = object()
|
class _Reasons(Enum):
|
||||||
UNSUPPORTED_MGF = object()
|
BACKEND_MISSING_INTERFACE = 0
|
||||||
UNSUPPORTED_PUBLIC_KEY_ALGORITHM = object()
|
UNSUPPORTED_HASH = 1
|
||||||
UNSUPPORTED_ELLIPTIC_CURVE = object()
|
UNSUPPORTED_CIPHER = 2
|
||||||
UNSUPPORTED_SERIALIZATION = object()
|
UNSUPPORTED_PADDING = 3
|
||||||
|
UNSUPPORTED_MGF = 4
|
||||||
|
UNSUPPORTED_PUBLIC_KEY_ALGORITHM = 5
|
||||||
|
UNSUPPORTED_ELLIPTIC_CURVE = 6
|
||||||
|
UNSUPPORTED_SERIALIZATION = 7
|
||||||
|
UNSUPPORTED_X509 = 8
|
||||||
|
UNSUPPORTED_EXCHANGE_ALGORITHM = 9
|
||||||
|
|
||||||
|
|
||||||
class UnsupportedAlgorithm(Exception):
|
class UnsupportedAlgorithm(Exception):
|
||||||
|
@ -52,12 +50,21 @@ class InvalidSignature(Exception):
|
||||||
|
|
||||||
|
|
||||||
class InternalError(Exception):
|
class InternalError(Exception):
|
||||||
pass
|
def __init__(self, msg, err_code):
|
||||||
|
super(InternalError, self).__init__(msg)
|
||||||
|
self.err_code = err_code
|
||||||
|
|
||||||
|
|
||||||
class InvalidKey(Exception):
|
class InvalidKey(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class InvalidToken(Exception):
|
InvalidToken = utils.deprecated(
|
||||||
pass
|
twofactor.InvalidToken,
|
||||||
|
__name__,
|
||||||
|
(
|
||||||
|
"The InvalidToken exception has moved to the "
|
||||||
|
"cryptography.hazmat.primitives.twofactor module"
|
||||||
|
),
|
||||||
|
utils.DeprecatedIn09
|
||||||
|
)
|
||||||
|
|
|
@ -1,15 +1,6 @@
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# This file is dual licensed under the terms of the Apache License, Version
|
||||||
# you may not use this file except in compliance with the License.
|
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
|
||||||
# You may obtain a copy of the License at
|
# for complete details.
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
# implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
|
@ -90,7 +81,7 @@ class Fernet(object):
|
||||||
except (TypeError, binascii.Error):
|
except (TypeError, binascii.Error):
|
||||||
raise InvalidToken
|
raise InvalidToken
|
||||||
|
|
||||||
if six.indexbytes(data, 0) != 0x80:
|
if not data or six.indexbytes(data, 0) != 0x80:
|
||||||
raise InvalidToken
|
raise InvalidToken
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -127,3 +118,24 @@ class Fernet(object):
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise InvalidToken
|
raise InvalidToken
|
||||||
return unpadded
|
return unpadded
|
||||||
|
|
||||||
|
|
||||||
|
class MultiFernet(object):
|
||||||
|
def __init__(self, fernets):
|
||||||
|
fernets = list(fernets)
|
||||||
|
if not fernets:
|
||||||
|
raise ValueError(
|
||||||
|
"MultiFernet requires at least one Fernet instance"
|
||||||
|
)
|
||||||
|
self._fernets = fernets
|
||||||
|
|
||||||
|
def encrypt(self, msg):
|
||||||
|
return self._fernets[0].encrypt(msg)
|
||||||
|
|
||||||
|
def decrypt(self, msg, ttl=None):
|
||||||
|
for f in self._fernets:
|
||||||
|
try:
|
||||||
|
return f.decrypt(msg, ttl)
|
||||||
|
except InvalidToken:
|
||||||
|
pass
|
||||||
|
raise InvalidToken
|
||||||
|
|
|
@ -1,14 +1,5 @@
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# This file is dual licensed under the terms of the Apache License, Version
|
||||||
# you may not use this file except in compliance with the License.
|
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
|
||||||
# You may obtain a copy of the License at
|
# for complete details.
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
# implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
|
@ -1,15 +1,6 @@
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# This file is dual licensed under the terms of the Apache License, Version
|
||||||
# you may not use this file except in compliance with the License.
|
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
|
||||||
# You may obtain a copy of the License at
|
# for complete details.
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
# implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
|
@ -26,8 +17,13 @@ def _available_backends():
|
||||||
|
|
||||||
if _available_backends_list is None:
|
if _available_backends_list is None:
|
||||||
_available_backends_list = [
|
_available_backends_list = [
|
||||||
backend.load(require=False)
|
# setuptools 11.3 deprecated support for the require parameter to
|
||||||
for backend in pkg_resources.iter_entry_points(
|
# load(), and introduced the new resolve() method instead.
|
||||||
|
# This can be removed if/when we can assume setuptools>=11.3. At
|
||||||
|
# some point we may wish to add a warning, to push people along,
|
||||||
|
# but at present this would result in too many warnings.
|
||||||
|
ep.resolve() if hasattr(ep, "resolve") else ep.load(require=False)
|
||||||
|
for ep in pkg_resources.iter_entry_points(
|
||||||
"cryptography.backends"
|
"cryptography.backends"
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,15 +1,6 @@
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# This file is dual licensed under the terms of the Apache License, Version
|
||||||
# you may not use this file except in compliance with the License.
|
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
|
||||||
# You may obtain a copy of the License at
|
# for complete details.
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
# implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,6 @@
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# This file is dual licensed under the terms of the Apache License, Version
|
||||||
# you may not use this file except in compliance with the License.
|
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
|
||||||
# You may obtain a copy of the License at
|
# for complete details.
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
# implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
|
@ -236,7 +227,8 @@ class Backend(object):
|
||||||
else:
|
else:
|
||||||
raise InternalError(
|
raise InternalError(
|
||||||
"The backend returned an unknown error, consider filing a bug."
|
"The backend returned an unknown error, consider filing a bug."
|
||||||
" Code: {0}.".format(response)
|
" Code: {0}.".format(response),
|
||||||
|
response
|
||||||
)
|
)
|
||||||
|
|
||||||
def _release_cipher_ctx(self, ctx):
|
def _release_cipher_ctx(self, ctx):
|
||||||
|
|
|
@ -1,15 +1,6 @@
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# This file is dual licensed under the terms of the Apache License, Version
|
||||||
# you may not use this file except in compliance with the License.
|
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
|
||||||
# You may obtain a copy of the License at
|
# for complete details.
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
# implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
|
@ -17,13 +8,14 @@ from cryptography import utils
|
||||||
from cryptography.exceptions import (
|
from cryptography.exceptions import (
|
||||||
InvalidTag, UnsupportedAlgorithm, _Reasons
|
InvalidTag, UnsupportedAlgorithm, _Reasons
|
||||||
)
|
)
|
||||||
from cryptography.hazmat.primitives import constant_time, interfaces
|
from cryptography.hazmat.primitives import ciphers, constant_time
|
||||||
|
from cryptography.hazmat.primitives.ciphers import modes
|
||||||
from cryptography.hazmat.primitives.ciphers.modes import (
|
from cryptography.hazmat.primitives.ciphers.modes import (
|
||||||
CFB, CFB8, CTR, OFB
|
CFB, CFB8, CTR, OFB
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@utils.register_interface(interfaces.CipherContext)
|
@utils.register_interface(ciphers.CipherContext)
|
||||||
class _CipherContext(object):
|
class _CipherContext(object):
|
||||||
def __init__(self, backend, cipher, mode, operation):
|
def __init__(self, backend, cipher, mode, operation):
|
||||||
self._backend = backend
|
self._backend = backend
|
||||||
|
@ -40,7 +32,7 @@ class _CipherContext(object):
|
||||||
# treat RC4 and other stream cipher block sizes).
|
# treat RC4 and other stream cipher block sizes).
|
||||||
# This bug has been filed as rdar://15589470
|
# This bug has been filed as rdar://15589470
|
||||||
self._bytes_processed = 0
|
self._bytes_processed = 0
|
||||||
if (isinstance(cipher, interfaces.BlockCipherAlgorithm) and not
|
if (isinstance(cipher, ciphers.BlockCipherAlgorithm) and not
|
||||||
isinstance(mode, (OFB, CFB, CFB8, CTR))):
|
isinstance(mode, (OFB, CFB, CFB8, CTR))):
|
||||||
self._byte_block_size = cipher.block_size // 8
|
self._byte_block_size = cipher.block_size // 8
|
||||||
else:
|
else:
|
||||||
|
@ -60,9 +52,9 @@ class _CipherContext(object):
|
||||||
ctx = self._backend._ffi.new("CCCryptorRef *")
|
ctx = self._backend._ffi.new("CCCryptorRef *")
|
||||||
ctx = self._backend._ffi.gc(ctx, self._backend._release_cipher_ctx)
|
ctx = self._backend._ffi.gc(ctx, self._backend._release_cipher_ctx)
|
||||||
|
|
||||||
if isinstance(mode, interfaces.ModeWithInitializationVector):
|
if isinstance(mode, modes.ModeWithInitializationVector):
|
||||||
iv_nonce = mode.initialization_vector
|
iv_nonce = mode.initialization_vector
|
||||||
elif isinstance(mode, interfaces.ModeWithNonce):
|
elif isinstance(mode, modes.ModeWithNonce):
|
||||||
iv_nonce = mode.nonce
|
iv_nonce = mode.nonce
|
||||||
else:
|
else:
|
||||||
iv_nonce = self._backend._ffi.NULL
|
iv_nonce = self._backend._ffi.NULL
|
||||||
|
@ -110,8 +102,8 @@ class _CipherContext(object):
|
||||||
return self._backend._ffi.buffer(buf)[:outlen[0]]
|
return self._backend._ffi.buffer(buf)[:outlen[0]]
|
||||||
|
|
||||||
|
|
||||||
@utils.register_interface(interfaces.AEADCipherContext)
|
@utils.register_interface(ciphers.AEADCipherContext)
|
||||||
@utils.register_interface(interfaces.AEADEncryptionContext)
|
@utils.register_interface(ciphers.AEADEncryptionContext)
|
||||||
class _GCMCipherContext(object):
|
class _GCMCipherContext(object):
|
||||||
def __init__(self, backend, cipher, mode, operation):
|
def __init__(self, backend, cipher, mode, operation):
|
||||||
self._backend = backend
|
self._backend = backend
|
||||||
|
@ -198,6 +190,4 @@ class _GCMCipherContext(object):
|
||||||
)
|
)
|
||||||
self._backend._check_cipher_response(res)
|
self._backend._check_cipher_response(res)
|
||||||
|
|
||||||
@property
|
tag = utils.read_only_property("_tag")
|
||||||
def tag(self):
|
|
||||||
return self._tag
|
|
||||||
|
|
|
@ -1,27 +1,18 @@
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# This file is dual licensed under the terms of the Apache License, Version
|
||||||
# you may not use this file except in compliance with the License.
|
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
|
||||||
# You may obtain a copy of the License at
|
# for complete details.
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
# implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
from cryptography import utils
|
from cryptography import utils
|
||||||
from cryptography.exceptions import UnsupportedAlgorithm, _Reasons
|
from cryptography.exceptions import UnsupportedAlgorithm, _Reasons
|
||||||
from cryptography.hazmat.primitives import interfaces
|
from cryptography.hazmat.primitives import hashes
|
||||||
|
|
||||||
|
|
||||||
@utils.register_interface(interfaces.HashContext)
|
@utils.register_interface(hashes.HashContext)
|
||||||
class _HashContext(object):
|
class _HashContext(object):
|
||||||
def __init__(self, backend, algorithm, ctx=None):
|
def __init__(self, backend, algorithm, ctx=None):
|
||||||
self.algorithm = algorithm
|
self._algorithm = algorithm
|
||||||
self._backend = backend
|
self._backend = backend
|
||||||
|
|
||||||
if ctx is None:
|
if ctx is None:
|
||||||
|
@ -39,6 +30,8 @@ class _HashContext(object):
|
||||||
|
|
||||||
self._ctx = ctx
|
self._ctx = ctx
|
||||||
|
|
||||||
|
algorithm = utils.read_only_property("_algorithm")
|
||||||
|
|
||||||
def copy(self):
|
def copy(self):
|
||||||
methods = self._backend._hash_mapping[self.algorithm.name]
|
methods = self._backend._hash_mapping[self.algorithm.name]
|
||||||
new_ctx = self._backend._ffi.new(methods.ctx)
|
new_ctx = self._backend._ffi.new(methods.ctx)
|
||||||
|
|
|
@ -1,27 +1,21 @@
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# This file is dual licensed under the terms of the Apache License, Version
|
||||||
# you may not use this file except in compliance with the License.
|
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
|
||||||
# You may obtain a copy of the License at
|
# for complete details.
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
# implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
from cryptography import utils
|
from cryptography import utils
|
||||||
from cryptography.exceptions import UnsupportedAlgorithm, _Reasons
|
from cryptography.exceptions import (
|
||||||
from cryptography.hazmat.primitives import interfaces
|
InvalidSignature, UnsupportedAlgorithm, _Reasons
|
||||||
|
)
|
||||||
|
from cryptography.hazmat.primitives import constant_time, hashes, interfaces
|
||||||
|
|
||||||
|
|
||||||
@utils.register_interface(interfaces.HashContext)
|
@utils.register_interface(interfaces.MACContext)
|
||||||
|
@utils.register_interface(hashes.HashContext)
|
||||||
class _HMACContext(object):
|
class _HMACContext(object):
|
||||||
def __init__(self, backend, key, algorithm, ctx=None):
|
def __init__(self, backend, key, algorithm, ctx=None):
|
||||||
self.algorithm = algorithm
|
self._algorithm = algorithm
|
||||||
self._backend = backend
|
self._backend = backend
|
||||||
if ctx is None:
|
if ctx is None:
|
||||||
ctx = self._backend._ffi.new("CCHmacContext *")
|
ctx = self._backend._ffi.new("CCHmacContext *")
|
||||||
|
@ -39,6 +33,8 @@ class _HMACContext(object):
|
||||||
self._ctx = ctx
|
self._ctx = ctx
|
||||||
self._key = key
|
self._key = key
|
||||||
|
|
||||||
|
algorithm = utils.read_only_property("_algorithm")
|
||||||
|
|
||||||
def copy(self):
|
def copy(self):
|
||||||
copied_ctx = self._backend._ffi.new("CCHmacContext *")
|
copied_ctx = self._backend._ffi.new("CCHmacContext *")
|
||||||
# CommonCrypto has no APIs for copying HMACs, so we have to copy the
|
# CommonCrypto has no APIs for copying HMACs, so we have to copy the
|
||||||
|
@ -56,3 +52,8 @@ class _HMACContext(object):
|
||||||
self.algorithm.digest_size)
|
self.algorithm.digest_size)
|
||||||
self._backend._lib.CCHmacFinal(self._ctx, buf)
|
self._backend._lib.CCHmacFinal(self._ctx, buf)
|
||||||
return self._backend._ffi.buffer(buf)[:]
|
return self._backend._ffi.buffer(buf)[:]
|
||||||
|
|
||||||
|
def verify(self, signature):
|
||||||
|
digest = self.finalize()
|
||||||
|
if not constant_time.bytes_eq(digest, signature):
|
||||||
|
raise InvalidSignature("Signature did not match digest.")
|
||||||
|
|
|
@ -1,15 +1,6 @@
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# This file is dual licensed under the terms of the Apache License, Version
|
||||||
# you may not use this file except in compliance with the License.
|
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
|
||||||
# You may obtain a copy of the License at
|
# for complete details.
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
# implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
|
@ -66,7 +57,7 @@ class HMACBackend(object):
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def create_hmac_ctx(self, key, algorithm):
|
def create_hmac_ctx(self, key, algorithm):
|
||||||
"""
|
"""
|
||||||
Create a HashContext for calculating a message authentication code.
|
Create a MACContext for calculating a message authentication code.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
@ -81,7 +72,7 @@ class CMACBackend(object):
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def create_cmac_ctx(self, algorithm):
|
def create_cmac_ctx(self, algorithm):
|
||||||
"""
|
"""
|
||||||
Create a CMACContext for calculating a message authentication code.
|
Create a MACContext for calculating a message authentication code.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
@ -111,39 +102,6 @@ class RSABackend(object):
|
||||||
of key_size bits.
|
of key_size bits.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def create_rsa_signature_ctx(self, private_key, padding, algorithm):
|
|
||||||
"""
|
|
||||||
Returns an object conforming to the AsymmetricSignatureContext
|
|
||||||
interface.
|
|
||||||
"""
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def create_rsa_verification_ctx(self, public_key, signature, padding,
|
|
||||||
algorithm):
|
|
||||||
"""
|
|
||||||
Returns an object conforming to the AsymmetricVerificationContext
|
|
||||||
interface.
|
|
||||||
"""
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def mgf1_hash_supported(self, algorithm):
|
|
||||||
"""
|
|
||||||
Return True if the hash algorithm is supported for MGF1 in PSS.
|
|
||||||
"""
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def decrypt_rsa(self, private_key, ciphertext, padding):
|
|
||||||
"""
|
|
||||||
Returns decrypted bytes.
|
|
||||||
"""
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def encrypt_rsa(self, public_key, plaintext, padding):
|
|
||||||
"""
|
|
||||||
Returns encrypted bytes.
|
|
||||||
"""
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def rsa_padding_supported(self, padding):
|
def rsa_padding_supported(self, padding):
|
||||||
"""
|
"""
|
||||||
|
@ -191,20 +149,6 @@ class DSABackend(object):
|
||||||
Generate a DSAPrivateKey instance using key size only.
|
Generate a DSAPrivateKey instance using key size only.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def create_dsa_signature_ctx(self, private_key, algorithm):
|
|
||||||
"""
|
|
||||||
Returns an object conforming to the AsymmetricSignatureContext
|
|
||||||
interface.
|
|
||||||
"""
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def create_dsa_verification_ctx(self, public_key, signature, algorithm):
|
|
||||||
"""
|
|
||||||
Returns an object conforming to the AsymmetricVerificationContext
|
|
||||||
interface.
|
|
||||||
"""
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def dsa_hash_supported(self, algorithm):
|
def dsa_hash_supported(self, algorithm):
|
||||||
"""
|
"""
|
||||||
|
@ -268,7 +212,13 @@ class EllipticCurveBackend(object):
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def load_elliptic_curve_private_numbers(self, numbers):
|
def load_elliptic_curve_private_numbers(self, numbers):
|
||||||
"""
|
"""
|
||||||
Return an EllipticCurvePublicKey provider using the given numbers.
|
Return an EllipticCurvePrivateKey provider using the given numbers.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def elliptic_curve_exchange_algorithm_supported(self, algorithm, curve):
|
||||||
|
"""
|
||||||
|
Returns whether the exchange algorithm is supported by this backend.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
@ -289,20 +239,107 @@ class PEMSerializationBackend(object):
|
||||||
|
|
||||||
|
|
||||||
@six.add_metaclass(abc.ABCMeta)
|
@six.add_metaclass(abc.ABCMeta)
|
||||||
class TraditionalOpenSSLSerializationBackend(object):
|
class DERSerializationBackend(object):
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def load_traditional_openssl_pem_private_key(self, data, password):
|
def load_der_private_key(self, data, password):
|
||||||
"""
|
"""
|
||||||
Load a private key from PEM encoded data, using password if the data
|
Loads a private key from DER encoded data. Uses the provided password
|
||||||
is encrypted.
|
if the data is encrypted.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def load_der_public_key(self, data):
|
||||||
|
"""
|
||||||
|
Loads a public key from DER encoded data.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
@six.add_metaclass(abc.ABCMeta)
|
@six.add_metaclass(abc.ABCMeta)
|
||||||
class PKCS8SerializationBackend(object):
|
class X509Backend(object):
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def load_pkcs8_pem_private_key(self, data, password):
|
def load_pem_x509_certificate(self, data):
|
||||||
"""
|
"""
|
||||||
Load a private key from PKCS8 encoded data, using password if the data
|
Load an X.509 certificate from PEM encoded data.
|
||||||
is encrypted.
|
"""
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def load_der_x509_certificate(self, data):
|
||||||
|
"""
|
||||||
|
Load an X.509 certificate from DER encoded data.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def load_der_x509_csr(self, data):
|
||||||
|
"""
|
||||||
|
Load an X.509 CSR from DER encoded data.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def load_pem_x509_csr(self, data):
|
||||||
|
"""
|
||||||
|
Load an X.509 CSR from PEM encoded data.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def create_x509_csr(self, builder, private_key, algorithm):
|
||||||
|
"""
|
||||||
|
Create and sign an X.509 CSR from a CSR builder object.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def create_x509_certificate(self, builder, private_key, algorithm):
|
||||||
|
"""
|
||||||
|
Create and sign an X.509 certificate from a CertificateBuilder object.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
@six.add_metaclass(abc.ABCMeta)
|
||||||
|
class DHBackend(object):
|
||||||
|
@abc.abstractmethod
|
||||||
|
def generate_dh_parameters(self, key_size):
|
||||||
|
"""
|
||||||
|
Generate a DHParameters instance with a modulus of key_size bits.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def generate_dh_private_key(self, parameters):
|
||||||
|
"""
|
||||||
|
Generate a DHPrivateKey instance with parameters as a DHParameters
|
||||||
|
object.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def generate_dh_private_key_and_parameters(self, key_size):
|
||||||
|
"""
|
||||||
|
Generate a DHPrivateKey instance using key size only.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def load_dh_private_numbers(self, numbers):
|
||||||
|
"""
|
||||||
|
Returns a DHPrivateKey provider.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def load_dh_public_numbers(self, numbers):
|
||||||
|
"""
|
||||||
|
Returns a DHPublicKey provider.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def load_dh_parameter_numbers(self, numbers):
|
||||||
|
"""
|
||||||
|
Returns a DHParameters provider.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def dh_exchange_algorithm_supported(self, exchange_algorithm):
|
||||||
|
"""
|
||||||
|
Returns whether the exchange algorithm is supported by this backend.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def dh_parameters_supported(self, p, g):
|
||||||
|
"""
|
||||||
|
Returns whether the backend supports DH with these parameter values.
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -1,41 +1,29 @@
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# This file is dual licensed under the terms of the Apache License, Version
|
||||||
# you may not use this file except in compliance with the License.
|
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
|
||||||
# You may obtain a copy of the License at
|
# for complete details.
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
# implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
import warnings
|
|
||||||
|
|
||||||
from cryptography import utils
|
from cryptography import utils
|
||||||
from cryptography.exceptions import UnsupportedAlgorithm, _Reasons
|
from cryptography.exceptions import UnsupportedAlgorithm, _Reasons
|
||||||
from cryptography.hazmat.backends.interfaces import (
|
from cryptography.hazmat.backends.interfaces import (
|
||||||
CMACBackend, CipherBackend, DSABackend, EllipticCurveBackend, HMACBackend,
|
CMACBackend, CipherBackend, DERSerializationBackend, DSABackend,
|
||||||
HashBackend, PBKDF2HMACBackend, PEMSerializationBackend,
|
EllipticCurveBackend, HMACBackend, HashBackend, PBKDF2HMACBackend,
|
||||||
PKCS8SerializationBackend, RSABackend,
|
PEMSerializationBackend, RSABackend, X509Backend
|
||||||
TraditionalOpenSSLSerializationBackend
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@utils.register_interface(CMACBackend)
|
@utils.register_interface(CMACBackend)
|
||||||
@utils.register_interface(CipherBackend)
|
@utils.register_interface(CipherBackend)
|
||||||
|
@utils.register_interface(DERSerializationBackend)
|
||||||
@utils.register_interface(HashBackend)
|
@utils.register_interface(HashBackend)
|
||||||
@utils.register_interface(HMACBackend)
|
@utils.register_interface(HMACBackend)
|
||||||
@utils.register_interface(PBKDF2HMACBackend)
|
@utils.register_interface(PBKDF2HMACBackend)
|
||||||
@utils.register_interface(PKCS8SerializationBackend)
|
|
||||||
@utils.register_interface(RSABackend)
|
@utils.register_interface(RSABackend)
|
||||||
@utils.register_interface(TraditionalOpenSSLSerializationBackend)
|
|
||||||
@utils.register_interface(DSABackend)
|
@utils.register_interface(DSABackend)
|
||||||
@utils.register_interface(EllipticCurveBackend)
|
@utils.register_interface(EllipticCurveBackend)
|
||||||
@utils.register_interface(PEMSerializationBackend)
|
@utils.register_interface(PEMSerializationBackend)
|
||||||
|
@utils.register_interface(X509Backend)
|
||||||
class MultiBackend(object):
|
class MultiBackend(object):
|
||||||
name = "multibackend"
|
name = "multibackend"
|
||||||
|
|
||||||
|
@ -47,33 +35,33 @@ class MultiBackend(object):
|
||||||
if isinstance(b, interface):
|
if isinstance(b, interface):
|
||||||
yield b
|
yield b
|
||||||
|
|
||||||
def cipher_supported(self, algorithm, mode):
|
def cipher_supported(self, cipher, mode):
|
||||||
return any(
|
return any(
|
||||||
b.cipher_supported(algorithm, mode)
|
b.cipher_supported(cipher, mode)
|
||||||
for b in self._filtered_backends(CipherBackend)
|
for b in self._filtered_backends(CipherBackend)
|
||||||
)
|
)
|
||||||
|
|
||||||
def create_symmetric_encryption_ctx(self, algorithm, mode):
|
def create_symmetric_encryption_ctx(self, cipher, mode):
|
||||||
for b in self._filtered_backends(CipherBackend):
|
for b in self._filtered_backends(CipherBackend):
|
||||||
try:
|
try:
|
||||||
return b.create_symmetric_encryption_ctx(algorithm, mode)
|
return b.create_symmetric_encryption_ctx(cipher, mode)
|
||||||
except UnsupportedAlgorithm:
|
except UnsupportedAlgorithm:
|
||||||
pass
|
pass
|
||||||
raise UnsupportedAlgorithm(
|
raise UnsupportedAlgorithm(
|
||||||
"cipher {0} in {1} mode is not supported by this backend.".format(
|
"cipher {0} in {1} mode is not supported by this backend.".format(
|
||||||
algorithm.name, mode.name if mode else mode),
|
cipher.name, mode.name if mode else mode),
|
||||||
_Reasons.UNSUPPORTED_CIPHER
|
_Reasons.UNSUPPORTED_CIPHER
|
||||||
)
|
)
|
||||||
|
|
||||||
def create_symmetric_decryption_ctx(self, algorithm, mode):
|
def create_symmetric_decryption_ctx(self, cipher, mode):
|
||||||
for b in self._filtered_backends(CipherBackend):
|
for b in self._filtered_backends(CipherBackend):
|
||||||
try:
|
try:
|
||||||
return b.create_symmetric_decryption_ctx(algorithm, mode)
|
return b.create_symmetric_decryption_ctx(cipher, mode)
|
||||||
except UnsupportedAlgorithm:
|
except UnsupportedAlgorithm:
|
||||||
pass
|
pass
|
||||||
raise UnsupportedAlgorithm(
|
raise UnsupportedAlgorithm(
|
||||||
"cipher {0} in {1} mode is not supported by this backend.".format(
|
"cipher {0} in {1} mode is not supported by this backend.".format(
|
||||||
algorithm.name, mode.name if mode else mode),
|
cipher.name, mode.name if mode else mode),
|
||||||
_Reasons.UNSUPPORTED_CIPHER
|
_Reasons.UNSUPPORTED_CIPHER
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -148,38 +136,6 @@ class MultiBackend(object):
|
||||||
raise UnsupportedAlgorithm("RSA is not supported by the backend.",
|
raise UnsupportedAlgorithm("RSA is not supported by the backend.",
|
||||||
_Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM)
|
_Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM)
|
||||||
|
|
||||||
def create_rsa_signature_ctx(self, private_key, padding, algorithm):
|
|
||||||
for b in self._filtered_backends(RSABackend):
|
|
||||||
return b.create_rsa_signature_ctx(private_key, padding, algorithm)
|
|
||||||
raise UnsupportedAlgorithm("RSA is not supported by the backend.",
|
|
||||||
_Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM)
|
|
||||||
|
|
||||||
def create_rsa_verification_ctx(self, public_key, signature, padding,
|
|
||||||
algorithm):
|
|
||||||
for b in self._filtered_backends(RSABackend):
|
|
||||||
return b.create_rsa_verification_ctx(public_key, signature,
|
|
||||||
padding, algorithm)
|
|
||||||
raise UnsupportedAlgorithm("RSA is not supported by the backend.",
|
|
||||||
_Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM)
|
|
||||||
|
|
||||||
def mgf1_hash_supported(self, algorithm):
|
|
||||||
for b in self._filtered_backends(RSABackend):
|
|
||||||
return b.mgf1_hash_supported(algorithm)
|
|
||||||
raise UnsupportedAlgorithm("RSA is not supported by the backend.",
|
|
||||||
_Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM)
|
|
||||||
|
|
||||||
def decrypt_rsa(self, private_key, ciphertext, padding):
|
|
||||||
for b in self._filtered_backends(RSABackend):
|
|
||||||
return b.decrypt_rsa(private_key, ciphertext, padding)
|
|
||||||
raise UnsupportedAlgorithm("RSA is not supported by the backend.",
|
|
||||||
_Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM)
|
|
||||||
|
|
||||||
def encrypt_rsa(self, public_key, plaintext, padding):
|
|
||||||
for b in self._filtered_backends(RSABackend):
|
|
||||||
return b.encrypt_rsa(public_key, plaintext, padding)
|
|
||||||
raise UnsupportedAlgorithm("RSA is not supported by the backend.",
|
|
||||||
_Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM)
|
|
||||||
|
|
||||||
def rsa_padding_supported(self, padding):
|
def rsa_padding_supported(self, padding):
|
||||||
for b in self._filtered_backends(RSABackend):
|
for b in self._filtered_backends(RSABackend):
|
||||||
return b.rsa_padding_supported(padding)
|
return b.rsa_padding_supported(padding)
|
||||||
|
@ -218,19 +174,6 @@ class MultiBackend(object):
|
||||||
raise UnsupportedAlgorithm("DSA is not supported by the backend.",
|
raise UnsupportedAlgorithm("DSA is not supported by the backend.",
|
||||||
_Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM)
|
_Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM)
|
||||||
|
|
||||||
def create_dsa_verification_ctx(self, public_key, signature, algorithm):
|
|
||||||
for b in self._filtered_backends(DSABackend):
|
|
||||||
return b.create_dsa_verification_ctx(public_key, signature,
|
|
||||||
algorithm)
|
|
||||||
raise UnsupportedAlgorithm("DSA is not supported by the backend.",
|
|
||||||
_Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM)
|
|
||||||
|
|
||||||
def create_dsa_signature_ctx(self, private_key, algorithm):
|
|
||||||
for b in self._filtered_backends(DSABackend):
|
|
||||||
return b.create_dsa_signature_ctx(private_key, algorithm)
|
|
||||||
raise UnsupportedAlgorithm("DSA is not supported by the backend.",
|
|
||||||
_Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM)
|
|
||||||
|
|
||||||
def dsa_hash_supported(self, algorithm):
|
def dsa_hash_supported(self, algorithm):
|
||||||
for b in self._filtered_backends(DSABackend):
|
for b in self._filtered_backends(DSABackend):
|
||||||
return b.dsa_hash_supported(algorithm)
|
return b.dsa_hash_supported(algorithm)
|
||||||
|
@ -255,6 +198,12 @@ class MultiBackend(object):
|
||||||
raise UnsupportedAlgorithm("DSA is not supported by the backend.",
|
raise UnsupportedAlgorithm("DSA is not supported by the backend.",
|
||||||
_Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM)
|
_Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM)
|
||||||
|
|
||||||
|
def load_dsa_parameter_numbers(self, numbers):
|
||||||
|
for b in self._filtered_backends(DSABackend):
|
||||||
|
return b.load_dsa_parameter_numbers(numbers)
|
||||||
|
raise UnsupportedAlgorithm("DSA is not supported by the backend.",
|
||||||
|
_Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM)
|
||||||
|
|
||||||
def cmac_algorithm_supported(self, algorithm):
|
def cmac_algorithm_supported(self, algorithm):
|
||||||
return any(
|
return any(
|
||||||
b.cmac_algorithm_supported(algorithm)
|
b.cmac_algorithm_supported(algorithm)
|
||||||
|
@ -298,24 +247,6 @@ class MultiBackend(object):
|
||||||
_Reasons.UNSUPPORTED_ELLIPTIC_CURVE
|
_Reasons.UNSUPPORTED_ELLIPTIC_CURVE
|
||||||
)
|
)
|
||||||
|
|
||||||
def elliptic_curve_private_key_from_numbers(self, numbers):
|
|
||||||
warnings.warn(
|
|
||||||
"elliptic_curve_private_key_from_numbers is deprecated and will "
|
|
||||||
"be removed in a future version.",
|
|
||||||
utils.DeprecatedIn06,
|
|
||||||
stacklevel=2
|
|
||||||
)
|
|
||||||
for b in self._filtered_backends(EllipticCurveBackend):
|
|
||||||
try:
|
|
||||||
return b.elliptic_curve_private_key_from_numbers(numbers)
|
|
||||||
except UnsupportedAlgorithm:
|
|
||||||
continue
|
|
||||||
|
|
||||||
raise UnsupportedAlgorithm(
|
|
||||||
"This backend does not support this elliptic curve.",
|
|
||||||
_Reasons.UNSUPPORTED_ELLIPTIC_CURVE
|
|
||||||
)
|
|
||||||
|
|
||||||
def load_elliptic_curve_private_numbers(self, numbers):
|
def load_elliptic_curve_private_numbers(self, numbers):
|
||||||
for b in self._filtered_backends(EllipticCurveBackend):
|
for b in self._filtered_backends(EllipticCurveBackend):
|
||||||
try:
|
try:
|
||||||
|
@ -328,24 +259,6 @@ class MultiBackend(object):
|
||||||
_Reasons.UNSUPPORTED_ELLIPTIC_CURVE
|
_Reasons.UNSUPPORTED_ELLIPTIC_CURVE
|
||||||
)
|
)
|
||||||
|
|
||||||
def elliptic_curve_public_key_from_numbers(self, numbers):
|
|
||||||
warnings.warn(
|
|
||||||
"elliptic_curve_public_key_from_numbers is deprecated and will "
|
|
||||||
"be removed in a future version.",
|
|
||||||
utils.DeprecatedIn06,
|
|
||||||
stacklevel=2
|
|
||||||
)
|
|
||||||
for b in self._filtered_backends(EllipticCurveBackend):
|
|
||||||
try:
|
|
||||||
return b.elliptic_curve_public_key_from_numbers(numbers)
|
|
||||||
except UnsupportedAlgorithm:
|
|
||||||
continue
|
|
||||||
|
|
||||||
raise UnsupportedAlgorithm(
|
|
||||||
"This backend does not support this elliptic curve.",
|
|
||||||
_Reasons.UNSUPPORTED_ELLIPTIC_CURVE
|
|
||||||
)
|
|
||||||
|
|
||||||
def load_elliptic_curve_public_numbers(self, numbers):
|
def load_elliptic_curve_public_numbers(self, numbers):
|
||||||
for b in self._filtered_backends(EllipticCurveBackend):
|
for b in self._filtered_backends(EllipticCurveBackend):
|
||||||
try:
|
try:
|
||||||
|
@ -358,6 +271,12 @@ class MultiBackend(object):
|
||||||
_Reasons.UNSUPPORTED_ELLIPTIC_CURVE
|
_Reasons.UNSUPPORTED_ELLIPTIC_CURVE
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def elliptic_curve_exchange_algorithm_supported(self, algorithm, curve):
|
||||||
|
return any(
|
||||||
|
b.elliptic_curve_exchange_algorithm_supported(algorithm, curve)
|
||||||
|
for b in self._filtered_backends(EllipticCurveBackend)
|
||||||
|
)
|
||||||
|
|
||||||
def load_pem_private_key(self, data, password):
|
def load_pem_private_key(self, data, password):
|
||||||
for b in self._filtered_backends(PEMSerializationBackend):
|
for b in self._filtered_backends(PEMSerializationBackend):
|
||||||
return b.load_pem_private_key(data, password)
|
return b.load_pem_private_key(data, password)
|
||||||
|
@ -376,22 +295,92 @@ class MultiBackend(object):
|
||||||
_Reasons.UNSUPPORTED_SERIALIZATION
|
_Reasons.UNSUPPORTED_SERIALIZATION
|
||||||
)
|
)
|
||||||
|
|
||||||
def load_pkcs8_pem_private_key(self, data, password):
|
def load_der_private_key(self, data, password):
|
||||||
for b in self._filtered_backends(PKCS8SerializationBackend):
|
for b in self._filtered_backends(DERSerializationBackend):
|
||||||
return b.load_pkcs8_pem_private_key(data, password)
|
return b.load_der_private_key(data, password)
|
||||||
|
|
||||||
raise UnsupportedAlgorithm(
|
raise UnsupportedAlgorithm(
|
||||||
"This backend does not support this key serialization.",
|
"This backend does not support this key serialization.",
|
||||||
_Reasons.UNSUPPORTED_SERIALIZATION
|
_Reasons.UNSUPPORTED_SERIALIZATION
|
||||||
)
|
)
|
||||||
|
|
||||||
def load_traditional_openssl_pem_private_key(self, data, password):
|
def load_der_public_key(self, data):
|
||||||
for b in self._filtered_backends(
|
for b in self._filtered_backends(DERSerializationBackend):
|
||||||
TraditionalOpenSSLSerializationBackend
|
return b.load_der_public_key(data)
|
||||||
):
|
|
||||||
return b.load_traditional_openssl_pem_private_key(data, password)
|
|
||||||
|
|
||||||
raise UnsupportedAlgorithm(
|
raise UnsupportedAlgorithm(
|
||||||
"This backend does not support this key serialization.",
|
"This backend does not support this key serialization.",
|
||||||
_Reasons.UNSUPPORTED_SERIALIZATION
|
_Reasons.UNSUPPORTED_SERIALIZATION
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def load_pem_x509_certificate(self, data):
|
||||||
|
for b in self._filtered_backends(X509Backend):
|
||||||
|
return b.load_pem_x509_certificate(data)
|
||||||
|
|
||||||
|
raise UnsupportedAlgorithm(
|
||||||
|
"This backend does not support X.509.",
|
||||||
|
_Reasons.UNSUPPORTED_X509
|
||||||
|
)
|
||||||
|
|
||||||
|
def load_der_x509_certificate(self, data):
|
||||||
|
for b in self._filtered_backends(X509Backend):
|
||||||
|
return b.load_der_x509_certificate(data)
|
||||||
|
|
||||||
|
raise UnsupportedAlgorithm(
|
||||||
|
"This backend does not support X.509.",
|
||||||
|
_Reasons.UNSUPPORTED_X509
|
||||||
|
)
|
||||||
|
|
||||||
|
def load_pem_x509_crl(self, data):
|
||||||
|
for b in self._filtered_backends(X509Backend):
|
||||||
|
return b.load_pem_x509_crl(data)
|
||||||
|
|
||||||
|
raise UnsupportedAlgorithm(
|
||||||
|
"This backend does not support X.509.",
|
||||||
|
_Reasons.UNSUPPORTED_X509
|
||||||
|
)
|
||||||
|
|
||||||
|
def load_der_x509_crl(self, data):
|
||||||
|
for b in self._filtered_backends(X509Backend):
|
||||||
|
return b.load_der_x509_crl(data)
|
||||||
|
|
||||||
|
raise UnsupportedAlgorithm(
|
||||||
|
"This backend does not support X.509.",
|
||||||
|
_Reasons.UNSUPPORTED_X509
|
||||||
|
)
|
||||||
|
|
||||||
|
def load_der_x509_csr(self, data):
|
||||||
|
for b in self._filtered_backends(X509Backend):
|
||||||
|
return b.load_der_x509_csr(data)
|
||||||
|
|
||||||
|
raise UnsupportedAlgorithm(
|
||||||
|
"This backend does not support X.509.",
|
||||||
|
_Reasons.UNSUPPORTED_X509
|
||||||
|
)
|
||||||
|
|
||||||
|
def load_pem_x509_csr(self, data):
|
||||||
|
for b in self._filtered_backends(X509Backend):
|
||||||
|
return b.load_pem_x509_csr(data)
|
||||||
|
|
||||||
|
raise UnsupportedAlgorithm(
|
||||||
|
"This backend does not support X.509.",
|
||||||
|
_Reasons.UNSUPPORTED_X509
|
||||||
|
)
|
||||||
|
|
||||||
|
def create_x509_csr(self, builder, private_key, algorithm):
|
||||||
|
for b in self._filtered_backends(X509Backend):
|
||||||
|
return b.create_x509_csr(builder, private_key, algorithm)
|
||||||
|
|
||||||
|
raise UnsupportedAlgorithm(
|
||||||
|
"This backend does not support X.509.",
|
||||||
|
_Reasons.UNSUPPORTED_X509
|
||||||
|
)
|
||||||
|
|
||||||
|
def create_x509_certificate(self, builder, private_key, algorithm):
|
||||||
|
for b in self._filtered_backends(X509Backend):
|
||||||
|
return b.create_x509_certificate(builder, private_key, algorithm)
|
||||||
|
|
||||||
|
raise UnsupportedAlgorithm(
|
||||||
|
"This backend does not support X.509.",
|
||||||
|
_Reasons.UNSUPPORTED_X509
|
||||||
|
)
|
||||||
|
|
|
@ -1,15 +1,6 @@
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# This file is dual licensed under the terms of the Apache License, Version
|
||||||
# you may not use this file except in compliance with the License.
|
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
|
||||||
# You may obtain a copy of the License at
|
# for complete details.
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
# implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,27 +1,18 @@
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# This file is dual licensed under the terms of the Apache License, Version
|
||||||
# you may not use this file except in compliance with the License.
|
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
|
||||||
# You may obtain a copy of the License at
|
# for complete details.
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
# implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
from cryptography import utils
|
from cryptography import utils
|
||||||
from cryptography.exceptions import InvalidTag, UnsupportedAlgorithm, _Reasons
|
from cryptography.exceptions import InvalidTag, UnsupportedAlgorithm, _Reasons
|
||||||
from cryptography.hazmat.primitives import interfaces
|
from cryptography.hazmat.primitives import ciphers
|
||||||
from cryptography.hazmat.primitives.ciphers.modes import GCM
|
from cryptography.hazmat.primitives.ciphers import modes
|
||||||
|
|
||||||
|
|
||||||
@utils.register_interface(interfaces.CipherContext)
|
@utils.register_interface(ciphers.CipherContext)
|
||||||
@utils.register_interface(interfaces.AEADCipherContext)
|
@utils.register_interface(ciphers.AEADCipherContext)
|
||||||
@utils.register_interface(interfaces.AEADEncryptionContext)
|
@utils.register_interface(ciphers.AEADEncryptionContext)
|
||||||
class _CipherContext(object):
|
class _CipherContext(object):
|
||||||
_ENCRYPT = 1
|
_ENCRYPT = 1
|
||||||
_DECRYPT = 0
|
_DECRYPT = 0
|
||||||
|
@ -33,7 +24,7 @@ class _CipherContext(object):
|
||||||
self._operation = operation
|
self._operation = operation
|
||||||
self._tag = None
|
self._tag = None
|
||||||
|
|
||||||
if isinstance(self._cipher, interfaces.BlockCipherAlgorithm):
|
if isinstance(self._cipher, ciphers.BlockCipherAlgorithm):
|
||||||
self._block_size = self._cipher.block_size
|
self._block_size = self._cipher.block_size
|
||||||
else:
|
else:
|
||||||
self._block_size = 1
|
self._block_size = 1
|
||||||
|
@ -63,9 +54,9 @@ class _CipherContext(object):
|
||||||
_Reasons.UNSUPPORTED_CIPHER
|
_Reasons.UNSUPPORTED_CIPHER
|
||||||
)
|
)
|
||||||
|
|
||||||
if isinstance(mode, interfaces.ModeWithInitializationVector):
|
if isinstance(mode, modes.ModeWithInitializationVector):
|
||||||
iv_nonce = mode.initialization_vector
|
iv_nonce = mode.initialization_vector
|
||||||
elif isinstance(mode, interfaces.ModeWithNonce):
|
elif isinstance(mode, modes.ModeWithNonce):
|
||||||
iv_nonce = mode.nonce
|
iv_nonce = mode.nonce
|
||||||
else:
|
else:
|
||||||
iv_nonce = self._backend._ffi.NULL
|
iv_nonce = self._backend._ffi.NULL
|
||||||
|
@ -75,24 +66,24 @@ class _CipherContext(object):
|
||||||
self._backend._ffi.NULL,
|
self._backend._ffi.NULL,
|
||||||
self._backend._ffi.NULL,
|
self._backend._ffi.NULL,
|
||||||
operation)
|
operation)
|
||||||
assert res != 0
|
self._backend.openssl_assert(res != 0)
|
||||||
# set the key length to handle variable key ciphers
|
# set the key length to handle variable key ciphers
|
||||||
res = self._backend._lib.EVP_CIPHER_CTX_set_key_length(
|
res = self._backend._lib.EVP_CIPHER_CTX_set_key_length(
|
||||||
ctx, len(cipher.key)
|
ctx, len(cipher.key)
|
||||||
)
|
)
|
||||||
assert res != 0
|
self._backend.openssl_assert(res != 0)
|
||||||
if isinstance(mode, GCM):
|
if isinstance(mode, modes.GCM):
|
||||||
res = self._backend._lib.EVP_CIPHER_CTX_ctrl(
|
res = self._backend._lib.EVP_CIPHER_CTX_ctrl(
|
||||||
ctx, self._backend._lib.EVP_CTRL_GCM_SET_IVLEN,
|
ctx, self._backend._lib.EVP_CTRL_GCM_SET_IVLEN,
|
||||||
len(iv_nonce), self._backend._ffi.NULL
|
len(iv_nonce), self._backend._ffi.NULL
|
||||||
)
|
)
|
||||||
assert res != 0
|
self._backend.openssl_assert(res != 0)
|
||||||
if operation == self._DECRYPT:
|
if operation == self._DECRYPT:
|
||||||
res = self._backend._lib.EVP_CIPHER_CTX_ctrl(
|
res = self._backend._lib.EVP_CIPHER_CTX_ctrl(
|
||||||
ctx, self._backend._lib.EVP_CTRL_GCM_SET_TAG,
|
ctx, self._backend._lib.EVP_CTRL_GCM_SET_TAG,
|
||||||
len(mode.tag), mode.tag
|
len(mode.tag), mode.tag
|
||||||
)
|
)
|
||||||
assert res != 0
|
self._backend.openssl_assert(res != 0)
|
||||||
|
|
||||||
# pass key/iv
|
# pass key/iv
|
||||||
res = self._backend._lib.EVP_CipherInit_ex(
|
res = self._backend._lib.EVP_CipherInit_ex(
|
||||||
|
@ -103,7 +94,7 @@ class _CipherContext(object):
|
||||||
iv_nonce,
|
iv_nonce,
|
||||||
operation
|
operation
|
||||||
)
|
)
|
||||||
assert res != 0
|
self._backend.openssl_assert(res != 0)
|
||||||
# We purposely disable padding here as it's handled higher up in the
|
# We purposely disable padding here as it's handled higher up in the
|
||||||
# API.
|
# API.
|
||||||
self._backend._lib.EVP_CIPHER_CTX_set_padding(ctx, 0)
|
self._backend._lib.EVP_CIPHER_CTX_set_padding(ctx, 0)
|
||||||
|
@ -116,7 +107,7 @@ class _CipherContext(object):
|
||||||
# should be taken only when length is zero and mode is not GCM because
|
# should be taken only when length is zero and mode is not GCM because
|
||||||
# AES GCM can return improper tag values if you don't call update
|
# AES GCM can return improper tag values if you don't call update
|
||||||
# with empty plaintext when authenticating AAD for ...reasons.
|
# with empty plaintext when authenticating AAD for ...reasons.
|
||||||
if len(data) == 0 and not isinstance(self._mode, GCM):
|
if len(data) == 0 and not isinstance(self._mode, modes.GCM):
|
||||||
return b""
|
return b""
|
||||||
|
|
||||||
buf = self._backend._ffi.new("unsigned char[]",
|
buf = self._backend._ffi.new("unsigned char[]",
|
||||||
|
@ -124,7 +115,7 @@ class _CipherContext(object):
|
||||||
outlen = self._backend._ffi.new("int *")
|
outlen = self._backend._ffi.new("int *")
|
||||||
res = self._backend._lib.EVP_CipherUpdate(self._ctx, buf, outlen, data,
|
res = self._backend._lib.EVP_CipherUpdate(self._ctx, buf, outlen, data,
|
||||||
len(data))
|
len(data))
|
||||||
assert res != 0
|
self._backend.openssl_assert(res != 0)
|
||||||
return self._backend._ffi.buffer(buf)[:outlen[0]]
|
return self._backend._ffi.buffer(buf)[:outlen[0]]
|
||||||
|
|
||||||
def finalize(self):
|
def finalize(self):
|
||||||
|
@ -133,7 +124,7 @@ class _CipherContext(object):
|
||||||
# even if you are only using authenticate_additional_data or the
|
# even if you are only using authenticate_additional_data or the
|
||||||
# GCM tag will be wrong. An (empty) call to update resolves this
|
# GCM tag will be wrong. An (empty) call to update resolves this
|
||||||
# and is harmless for all other versions of OpenSSL.
|
# and is harmless for all other versions of OpenSSL.
|
||||||
if isinstance(self._mode, GCM):
|
if isinstance(self._mode, modes.GCM):
|
||||||
self.update(b"")
|
self.update(b"")
|
||||||
|
|
||||||
buf = self._backend._ffi.new("unsigned char[]", self._block_size)
|
buf = self._backend._ffi.new("unsigned char[]", self._block_size)
|
||||||
|
@ -142,12 +133,11 @@ class _CipherContext(object):
|
||||||
if res == 0:
|
if res == 0:
|
||||||
errors = self._backend._consume_errors()
|
errors = self._backend._consume_errors()
|
||||||
|
|
||||||
if not errors and isinstance(self._mode, GCM):
|
if not errors and isinstance(self._mode, modes.GCM):
|
||||||
raise InvalidTag
|
raise InvalidTag
|
||||||
|
|
||||||
assert errors
|
self._backend.openssl_assert(
|
||||||
|
errors[0][1:] == (
|
||||||
if errors[0][1:] == (
|
|
||||||
self._backend._lib.ERR_LIB_EVP,
|
self._backend._lib.ERR_LIB_EVP,
|
||||||
self._backend._lib.EVP_F_EVP_ENCRYPTFINAL_EX,
|
self._backend._lib.EVP_F_EVP_ENCRYPTFINAL_EX,
|
||||||
self._backend._lib.EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH
|
self._backend._lib.EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH
|
||||||
|
@ -155,15 +145,14 @@ class _CipherContext(object):
|
||||||
self._backend._lib.ERR_LIB_EVP,
|
self._backend._lib.ERR_LIB_EVP,
|
||||||
self._backend._lib.EVP_F_EVP_DECRYPTFINAL_EX,
|
self._backend._lib.EVP_F_EVP_DECRYPTFINAL_EX,
|
||||||
self._backend._lib.EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH
|
self._backend._lib.EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH
|
||||||
):
|
)
|
||||||
|
)
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"The length of the provided data is not a multiple of "
|
"The length of the provided data is not a multiple of "
|
||||||
"the block length."
|
"the block length."
|
||||||
)
|
)
|
||||||
else:
|
|
||||||
raise self._backend._unknown_error(errors[0])
|
|
||||||
|
|
||||||
if (isinstance(self._mode, GCM) and
|
if (isinstance(self._mode, modes.GCM) and
|
||||||
self._operation == self._ENCRYPT):
|
self._operation == self._ENCRYPT):
|
||||||
block_byte_size = self._block_size // 8
|
block_byte_size = self._block_size // 8
|
||||||
tag_buf = self._backend._ffi.new(
|
tag_buf = self._backend._ffi.new(
|
||||||
|
@ -173,11 +162,11 @@ class _CipherContext(object):
|
||||||
self._ctx, self._backend._lib.EVP_CTRL_GCM_GET_TAG,
|
self._ctx, self._backend._lib.EVP_CTRL_GCM_GET_TAG,
|
||||||
block_byte_size, tag_buf
|
block_byte_size, tag_buf
|
||||||
)
|
)
|
||||||
assert res != 0
|
self._backend.openssl_assert(res != 0)
|
||||||
self._tag = self._backend._ffi.buffer(tag_buf)[:]
|
self._tag = self._backend._ffi.buffer(tag_buf)[:]
|
||||||
|
|
||||||
res = self._backend._lib.EVP_CIPHER_CTX_cleanup(self._ctx)
|
res = self._backend._lib.EVP_CIPHER_CTX_cleanup(self._ctx)
|
||||||
assert res == 1
|
self._backend.openssl_assert(res == 1)
|
||||||
return self._backend._ffi.buffer(buf)[:outlen[0]]
|
return self._backend._ffi.buffer(buf)[:outlen[0]]
|
||||||
|
|
||||||
def authenticate_additional_data(self, data):
|
def authenticate_additional_data(self, data):
|
||||||
|
@ -185,14 +174,12 @@ class _CipherContext(object):
|
||||||
res = self._backend._lib.EVP_CipherUpdate(
|
res = self._backend._lib.EVP_CipherUpdate(
|
||||||
self._ctx, self._backend._ffi.NULL, outlen, data, len(data)
|
self._ctx, self._backend._ffi.NULL, outlen, data, len(data)
|
||||||
)
|
)
|
||||||
assert res != 0
|
self._backend.openssl_assert(res != 0)
|
||||||
|
|
||||||
@property
|
tag = utils.read_only_property("_tag")
|
||||||
def tag(self):
|
|
||||||
return self._tag
|
|
||||||
|
|
||||||
|
|
||||||
@utils.register_interface(interfaces.CipherContext)
|
@utils.register_interface(ciphers.CipherContext)
|
||||||
class _AESCTRCipherContext(object):
|
class _AESCTRCipherContext(object):
|
||||||
"""
|
"""
|
||||||
This is needed to provide support for AES CTR mode in OpenSSL 0.9.8. It can
|
This is needed to provide support for AES CTR mode in OpenSSL 0.9.8. It can
|
||||||
|
@ -202,11 +189,10 @@ class _AESCTRCipherContext(object):
|
||||||
self._backend = backend
|
self._backend = backend
|
||||||
|
|
||||||
self._key = self._backend._ffi.new("AES_KEY *")
|
self._key = self._backend._ffi.new("AES_KEY *")
|
||||||
assert self._key != self._backend._ffi.NULL
|
|
||||||
res = self._backend._lib.AES_set_encrypt_key(
|
res = self._backend._lib.AES_set_encrypt_key(
|
||||||
cipher.key, len(cipher.key) * 8, self._key
|
cipher.key, len(cipher.key) * 8, self._key
|
||||||
)
|
)
|
||||||
assert res == 0
|
self._backend.openssl_assert(res == 0)
|
||||||
self._ecount = self._backend._ffi.new("char[]", 16)
|
self._ecount = self._backend._ffi.new("char[]", 16)
|
||||||
self._nonce = self._backend._ffi.new("char[16]", mode.nonce)
|
self._nonce = self._backend._ffi.new("char[16]", mode.nonce)
|
||||||
self._num = self._backend._ffi.new("unsigned int *", 0)
|
self._num = self._backend._ffi.new("unsigned int *", 0)
|
||||||
|
|
|
@ -1,26 +1,19 @@
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# This file is dual licensed under the terms of the Apache License, Version
|
||||||
# you may not use this file except in compliance with the License.
|
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
|
||||||
# You may obtain a copy of the License at
|
# for complete details.
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
# implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
|
|
||||||
from cryptography import utils
|
from cryptography import utils
|
||||||
from cryptography.exceptions import UnsupportedAlgorithm, _Reasons
|
from cryptography.exceptions import (
|
||||||
from cryptography.hazmat.primitives import interfaces
|
InvalidSignature, UnsupportedAlgorithm, _Reasons
|
||||||
|
)
|
||||||
|
from cryptography.hazmat.primitives import constant_time, interfaces
|
||||||
from cryptography.hazmat.primitives.ciphers.modes import CBC
|
from cryptography.hazmat.primitives.ciphers.modes import CBC
|
||||||
|
|
||||||
|
|
||||||
@utils.register_interface(interfaces.CMACContext)
|
@utils.register_interface(interfaces.MACContext)
|
||||||
class _CMACContext(object):
|
class _CMACContext(object):
|
||||||
def __init__(self, backend, algorithm, ctx=None):
|
def __init__(self, backend, algorithm, ctx=None):
|
||||||
if not backend.cmac_algorithm_supported(algorithm):
|
if not backend.cmac_algorithm_supported(algorithm):
|
||||||
|
@ -40,7 +33,7 @@ class _CMACContext(object):
|
||||||
|
|
||||||
ctx = self._backend._lib.CMAC_CTX_new()
|
ctx = self._backend._lib.CMAC_CTX_new()
|
||||||
|
|
||||||
assert ctx != self._backend._ffi.NULL
|
self._backend.openssl_assert(ctx != self._backend._ffi.NULL)
|
||||||
ctx = self._backend._ffi.gc(ctx, self._backend._lib.CMAC_CTX_free)
|
ctx = self._backend._ffi.gc(ctx, self._backend._lib.CMAC_CTX_free)
|
||||||
|
|
||||||
self._backend._lib.CMAC_Init(
|
self._backend._lib.CMAC_Init(
|
||||||
|
@ -50,9 +43,11 @@ class _CMACContext(object):
|
||||||
|
|
||||||
self._ctx = ctx
|
self._ctx = ctx
|
||||||
|
|
||||||
|
algorithm = utils.read_only_property("_algorithm")
|
||||||
|
|
||||||
def update(self, data):
|
def update(self, data):
|
||||||
res = self._backend._lib.CMAC_Update(self._ctx, data, len(data))
|
res = self._backend._lib.CMAC_Update(self._ctx, data, len(data))
|
||||||
assert res == 1
|
self._backend.openssl_assert(res == 1)
|
||||||
|
|
||||||
def finalize(self):
|
def finalize(self):
|
||||||
buf = self._backend._ffi.new("unsigned char[]", self._output_length)
|
buf = self._backend._ffi.new("unsigned char[]", self._output_length)
|
||||||
|
@ -60,7 +55,7 @@ class _CMACContext(object):
|
||||||
res = self._backend._lib.CMAC_Final(
|
res = self._backend._lib.CMAC_Final(
|
||||||
self._ctx, buf, length
|
self._ctx, buf, length
|
||||||
)
|
)
|
||||||
assert res == 1
|
self._backend.openssl_assert(res == 1)
|
||||||
|
|
||||||
self._ctx = None
|
self._ctx = None
|
||||||
|
|
||||||
|
@ -74,7 +69,12 @@ class _CMACContext(object):
|
||||||
res = self._backend._lib.CMAC_CTX_copy(
|
res = self._backend._lib.CMAC_CTX_copy(
|
||||||
copied_ctx, self._ctx
|
copied_ctx, self._ctx
|
||||||
)
|
)
|
||||||
assert res == 1
|
self._backend.openssl_assert(res == 1)
|
||||||
return _CMACContext(
|
return _CMACContext(
|
||||||
self._backend, self._algorithm, ctx=copied_ctx
|
self._backend, self._algorithm, ctx=copied_ctx
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def verify(self, signature):
|
||||||
|
digest = self.finalize()
|
||||||
|
if not constant_time.bytes_eq(digest, signature):
|
||||||
|
raise InvalidSignature("Signature did not match digest.")
|
||||||
|
|
|
@ -1,28 +1,32 @@
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# This file is dual licensed under the terms of the Apache License, Version
|
||||||
# you may not use this file except in compliance with the License.
|
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
|
||||||
# You may obtain a copy of the License at
|
# for complete details.
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
# implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
from cryptography import utils
|
from cryptography import utils
|
||||||
from cryptography.exceptions import InvalidSignature
|
from cryptography.exceptions import InvalidSignature
|
||||||
from cryptography.hazmat.primitives import hashes, interfaces
|
from cryptography.hazmat.backends.openssl.utils import _truncate_digest
|
||||||
from cryptography.hazmat.primitives.asymmetric import dsa
|
from cryptography.hazmat.primitives import hashes, serialization
|
||||||
from cryptography.hazmat.primitives.interfaces import (
|
from cryptography.hazmat.primitives.asymmetric import (
|
||||||
DSAParametersWithNumbers, DSAPrivateKeyWithNumbers, DSAPublicKeyWithNumbers
|
AsymmetricSignatureContext, AsymmetricVerificationContext, dsa
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@utils.register_interface(interfaces.AsymmetricVerificationContext)
|
def _truncate_digest_for_dsa(dsa_cdata, digest, backend):
|
||||||
|
"""
|
||||||
|
This function truncates digests that are longer than a given DS
|
||||||
|
key's length so they can be signed. OpenSSL does this for us in
|
||||||
|
1.0.0c+ and it isn't needed in 0.9.8, but that leaves us with three
|
||||||
|
releases (1.0.0, 1.0.0a, and 1.0.0b) where this is a problem. This
|
||||||
|
truncation is not required in 0.9.8 because DSA is limited to SHA-1.
|
||||||
|
"""
|
||||||
|
|
||||||
|
order_bits = backend._lib.BN_num_bits(dsa_cdata.q)
|
||||||
|
return _truncate_digest(digest, order_bits)
|
||||||
|
|
||||||
|
|
||||||
|
@utils.register_interface(AsymmetricVerificationContext)
|
||||||
class _DSAVerificationContext(object):
|
class _DSAVerificationContext(object):
|
||||||
def __init__(self, backend, public_key, signature, algorithm):
|
def __init__(self, backend, public_key, signature, algorithm):
|
||||||
self._backend = backend
|
self._backend = backend
|
||||||
|
@ -36,11 +40,12 @@ class _DSAVerificationContext(object):
|
||||||
self._hash_ctx.update(data)
|
self._hash_ctx.update(data)
|
||||||
|
|
||||||
def verify(self):
|
def verify(self):
|
||||||
self._dsa_cdata = self._backend._ffi.gc(self._public_key._dsa_cdata,
|
|
||||||
self._backend._lib.DSA_free)
|
|
||||||
|
|
||||||
data_to_verify = self._hash_ctx.finalize()
|
data_to_verify = self._hash_ctx.finalize()
|
||||||
|
|
||||||
|
data_to_verify = _truncate_digest_for_dsa(
|
||||||
|
self._public_key._dsa_cdata, data_to_verify, self._backend
|
||||||
|
)
|
||||||
|
|
||||||
# The first parameter passed to DSA_verify is unused by OpenSSL but
|
# The first parameter passed to DSA_verify is unused by OpenSSL but
|
||||||
# must be an integer.
|
# must be an integer.
|
||||||
res = self._backend._lib.DSA_verify(
|
res = self._backend._lib.DSA_verify(
|
||||||
|
@ -48,15 +53,11 @@ class _DSAVerificationContext(object):
|
||||||
len(self._signature), self._public_key._dsa_cdata)
|
len(self._signature), self._public_key._dsa_cdata)
|
||||||
|
|
||||||
if res != 1:
|
if res != 1:
|
||||||
errors = self._backend._consume_errors()
|
self._backend._consume_errors()
|
||||||
assert errors
|
|
||||||
if res == -1:
|
|
||||||
assert errors[0].lib == self._backend._lib.ERR_LIB_ASN1
|
|
||||||
|
|
||||||
raise InvalidSignature
|
raise InvalidSignature
|
||||||
|
|
||||||
|
|
||||||
@utils.register_interface(interfaces.AsymmetricSignatureContext)
|
@utils.register_interface(AsymmetricSignatureContext)
|
||||||
class _DSASignatureContext(object):
|
class _DSASignatureContext(object):
|
||||||
def __init__(self, backend, private_key, algorithm):
|
def __init__(self, backend, private_key, algorithm):
|
||||||
self._backend = backend
|
self._backend = backend
|
||||||
|
@ -69,6 +70,9 @@ class _DSASignatureContext(object):
|
||||||
|
|
||||||
def finalize(self):
|
def finalize(self):
|
||||||
data_to_sign = self._hash_ctx.finalize()
|
data_to_sign = self._hash_ctx.finalize()
|
||||||
|
data_to_sign = _truncate_digest_for_dsa(
|
||||||
|
self._private_key._dsa_cdata, data_to_sign, self._backend
|
||||||
|
)
|
||||||
sig_buf_len = self._backend._lib.DSA_size(self._private_key._dsa_cdata)
|
sig_buf_len = self._backend._lib.DSA_size(self._private_key._dsa_cdata)
|
||||||
sig_buf = self._backend._ffi.new("unsigned char[]", sig_buf_len)
|
sig_buf = self._backend._ffi.new("unsigned char[]", sig_buf_len)
|
||||||
buflen = self._backend._ffi.new("unsigned int *")
|
buflen = self._backend._ffi.new("unsigned int *")
|
||||||
|
@ -78,13 +82,13 @@ class _DSASignatureContext(object):
|
||||||
res = self._backend._lib.DSA_sign(
|
res = self._backend._lib.DSA_sign(
|
||||||
0, data_to_sign, len(data_to_sign), sig_buf,
|
0, data_to_sign, len(data_to_sign), sig_buf,
|
||||||
buflen, self._private_key._dsa_cdata)
|
buflen, self._private_key._dsa_cdata)
|
||||||
assert res == 1
|
self._backend.openssl_assert(res == 1)
|
||||||
assert buflen[0]
|
self._backend.openssl_assert(buflen[0])
|
||||||
|
|
||||||
return self._backend._ffi.buffer(sig_buf)[:buflen[0]]
|
return self._backend._ffi.buffer(sig_buf)[:buflen[0]]
|
||||||
|
|
||||||
|
|
||||||
@utils.register_interface(DSAParametersWithNumbers)
|
@utils.register_interface(dsa.DSAParametersWithNumbers)
|
||||||
class _DSAParameters(object):
|
class _DSAParameters(object):
|
||||||
def __init__(self, backend, dsa_cdata):
|
def __init__(self, backend, dsa_cdata):
|
||||||
self._backend = backend
|
self._backend = backend
|
||||||
|
@ -101,19 +105,18 @@ class _DSAParameters(object):
|
||||||
return self._backend.generate_dsa_private_key(self)
|
return self._backend.generate_dsa_private_key(self)
|
||||||
|
|
||||||
|
|
||||||
@utils.register_interface(DSAPrivateKeyWithNumbers)
|
@utils.register_interface(dsa.DSAPrivateKeyWithSerialization)
|
||||||
class _DSAPrivateKey(object):
|
class _DSAPrivateKey(object):
|
||||||
def __init__(self, backend, dsa_cdata):
|
def __init__(self, backend, dsa_cdata, evp_pkey):
|
||||||
self._backend = backend
|
self._backend = backend
|
||||||
self._dsa_cdata = dsa_cdata
|
self._dsa_cdata = dsa_cdata
|
||||||
|
self._evp_pkey = evp_pkey
|
||||||
self._key_size = self._backend._lib.BN_num_bits(self._dsa_cdata.p)
|
self._key_size = self._backend._lib.BN_num_bits(self._dsa_cdata.p)
|
||||||
|
|
||||||
@property
|
key_size = utils.read_only_property("_key_size")
|
||||||
def key_size(self):
|
|
||||||
return self._key_size
|
|
||||||
|
|
||||||
def signer(self, algorithm):
|
def signer(self, signature_algorithm):
|
||||||
return _DSASignatureContext(self._backend, self, algorithm)
|
return _DSASignatureContext(self._backend, self, signature_algorithm)
|
||||||
|
|
||||||
def private_numbers(self):
|
def private_numbers(self):
|
||||||
return dsa.DSAPrivateNumbers(
|
return dsa.DSAPrivateNumbers(
|
||||||
|
@ -130,7 +133,7 @@ class _DSAPrivateKey(object):
|
||||||
|
|
||||||
def public_key(self):
|
def public_key(self):
|
||||||
dsa_cdata = self._backend._lib.DSA_new()
|
dsa_cdata = self._backend._lib.DSA_new()
|
||||||
assert dsa_cdata != self._backend._ffi.NULL
|
self._backend.openssl_assert(dsa_cdata != self._backend._ffi.NULL)
|
||||||
dsa_cdata = self._backend._ffi.gc(
|
dsa_cdata = self._backend._ffi.gc(
|
||||||
dsa_cdata, self._backend._lib.DSA_free
|
dsa_cdata, self._backend._lib.DSA_free
|
||||||
)
|
)
|
||||||
|
@ -138,11 +141,12 @@ class _DSAPrivateKey(object):
|
||||||
dsa_cdata.q = self._backend._lib.BN_dup(self._dsa_cdata.q)
|
dsa_cdata.q = self._backend._lib.BN_dup(self._dsa_cdata.q)
|
||||||
dsa_cdata.g = self._backend._lib.BN_dup(self._dsa_cdata.g)
|
dsa_cdata.g = self._backend._lib.BN_dup(self._dsa_cdata.g)
|
||||||
dsa_cdata.pub_key = self._backend._lib.BN_dup(self._dsa_cdata.pub_key)
|
dsa_cdata.pub_key = self._backend._lib.BN_dup(self._dsa_cdata.pub_key)
|
||||||
return _DSAPublicKey(self._backend, dsa_cdata)
|
evp_pkey = self._backend._dsa_cdata_to_evp_pkey(dsa_cdata)
|
||||||
|
return _DSAPublicKey(self._backend, dsa_cdata, evp_pkey)
|
||||||
|
|
||||||
def parameters(self):
|
def parameters(self):
|
||||||
dsa_cdata = self._backend._lib.DSA_new()
|
dsa_cdata = self._backend._lib.DSA_new()
|
||||||
assert dsa_cdata != self._backend._ffi.NULL
|
self._backend.openssl_assert(dsa_cdata != self._backend._ffi.NULL)
|
||||||
dsa_cdata = self._backend._ffi.gc(
|
dsa_cdata = self._backend._ffi.gc(
|
||||||
dsa_cdata, self._backend._lib.DSA_free
|
dsa_cdata, self._backend._lib.DSA_free
|
||||||
)
|
)
|
||||||
|
@ -151,21 +155,32 @@ class _DSAPrivateKey(object):
|
||||||
dsa_cdata.g = self._backend._lib.BN_dup(self._dsa_cdata.g)
|
dsa_cdata.g = self._backend._lib.BN_dup(self._dsa_cdata.g)
|
||||||
return _DSAParameters(self._backend, dsa_cdata)
|
return _DSAParameters(self._backend, dsa_cdata)
|
||||||
|
|
||||||
|
def private_bytes(self, encoding, format, encryption_algorithm):
|
||||||
|
return self._backend._private_key_bytes(
|
||||||
|
encoding,
|
||||||
|
format,
|
||||||
|
encryption_algorithm,
|
||||||
|
self._evp_pkey,
|
||||||
|
self._dsa_cdata
|
||||||
|
)
|
||||||
|
|
||||||
@utils.register_interface(DSAPublicKeyWithNumbers)
|
|
||||||
|
@utils.register_interface(dsa.DSAPublicKeyWithSerialization)
|
||||||
class _DSAPublicKey(object):
|
class _DSAPublicKey(object):
|
||||||
def __init__(self, backend, dsa_cdata):
|
def __init__(self, backend, dsa_cdata, evp_pkey):
|
||||||
self._backend = backend
|
self._backend = backend
|
||||||
self._dsa_cdata = dsa_cdata
|
self._dsa_cdata = dsa_cdata
|
||||||
|
self._evp_pkey = evp_pkey
|
||||||
self._key_size = self._backend._lib.BN_num_bits(self._dsa_cdata.p)
|
self._key_size = self._backend._lib.BN_num_bits(self._dsa_cdata.p)
|
||||||
|
|
||||||
@property
|
key_size = utils.read_only_property("_key_size")
|
||||||
def key_size(self):
|
|
||||||
return self._key_size
|
def verifier(self, signature, signature_algorithm):
|
||||||
|
if not isinstance(signature, bytes):
|
||||||
|
raise TypeError("signature must be bytes.")
|
||||||
|
|
||||||
def verifier(self, signature, algorithm):
|
|
||||||
return _DSAVerificationContext(
|
return _DSAVerificationContext(
|
||||||
self._backend, self, signature, algorithm
|
self._backend, self, signature, signature_algorithm
|
||||||
)
|
)
|
||||||
|
|
||||||
def public_numbers(self):
|
def public_numbers(self):
|
||||||
|
@ -180,7 +195,7 @@ class _DSAPublicKey(object):
|
||||||
|
|
||||||
def parameters(self):
|
def parameters(self):
|
||||||
dsa_cdata = self._backend._lib.DSA_new()
|
dsa_cdata = self._backend._lib.DSA_new()
|
||||||
assert dsa_cdata != self._backend._ffi.NULL
|
self._backend.openssl_assert(dsa_cdata != self._backend._ffi.NULL)
|
||||||
dsa_cdata = self._backend._ffi.gc(
|
dsa_cdata = self._backend._ffi.gc(
|
||||||
dsa_cdata, self._backend._lib.DSA_free
|
dsa_cdata, self._backend._lib.DSA_free
|
||||||
)
|
)
|
||||||
|
@ -188,3 +203,16 @@ class _DSAPublicKey(object):
|
||||||
dsa_cdata.q = self._backend._lib.BN_dup(self._dsa_cdata.q)
|
dsa_cdata.q = self._backend._lib.BN_dup(self._dsa_cdata.q)
|
||||||
dsa_cdata.g = self._backend._lib.BN_dup(self._dsa_cdata.g)
|
dsa_cdata.g = self._backend._lib.BN_dup(self._dsa_cdata.g)
|
||||||
return _DSAParameters(self._backend, dsa_cdata)
|
return _DSAParameters(self._backend, dsa_cdata)
|
||||||
|
|
||||||
|
def public_bytes(self, encoding, format):
|
||||||
|
if format is serialization.PublicFormat.PKCS1:
|
||||||
|
raise ValueError(
|
||||||
|
"DSA public keys do not support PKCS1 serialization"
|
||||||
|
)
|
||||||
|
|
||||||
|
return self._backend._public_key_bytes(
|
||||||
|
encoding,
|
||||||
|
format,
|
||||||
|
self._evp_pkey,
|
||||||
|
None
|
||||||
|
)
|
||||||
|
|
|
@ -1,26 +1,18 @@
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# This file is dual licensed under the terms of the Apache License, Version
|
||||||
# you may not use this file except in compliance with the License.
|
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
|
||||||
# You may obtain a copy of the License at
|
# for complete details.
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
# implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
import six
|
|
||||||
|
|
||||||
from cryptography import utils
|
from cryptography import utils
|
||||||
from cryptography.exceptions import (
|
from cryptography.exceptions import (
|
||||||
InvalidSignature, UnsupportedAlgorithm, _Reasons
|
InvalidSignature, UnsupportedAlgorithm, _Reasons
|
||||||
)
|
)
|
||||||
from cryptography.hazmat.primitives import hashes, interfaces
|
from cryptography.hazmat.backends.openssl.utils import _truncate_digest
|
||||||
from cryptography.hazmat.primitives.asymmetric import ec
|
from cryptography.hazmat.primitives import hashes, serialization
|
||||||
|
from cryptography.hazmat.primitives.asymmetric import (
|
||||||
|
AsymmetricSignatureContext, AsymmetricVerificationContext, ec
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def _truncate_digest_for_ecdsa(ec_key_cdata, digest, backend):
|
def _truncate_digest_for_ecdsa(ec_key_cdata, digest, backend):
|
||||||
|
@ -34,49 +26,52 @@ def _truncate_digest_for_ecdsa(ec_key_cdata, digest, backend):
|
||||||
_lib = backend._lib
|
_lib = backend._lib
|
||||||
_ffi = backend._ffi
|
_ffi = backend._ffi
|
||||||
|
|
||||||
digest_len = len(digest)
|
|
||||||
|
|
||||||
group = _lib.EC_KEY_get0_group(ec_key_cdata)
|
group = _lib.EC_KEY_get0_group(ec_key_cdata)
|
||||||
|
|
||||||
with backend._tmp_bn_ctx() as bn_ctx:
|
with backend._tmp_bn_ctx() as bn_ctx:
|
||||||
order = _lib.BN_CTX_get(bn_ctx)
|
order = _lib.BN_CTX_get(bn_ctx)
|
||||||
assert order != _ffi.NULL
|
backend.openssl_assert(order != _ffi.NULL)
|
||||||
|
|
||||||
res = _lib.EC_GROUP_get_order(group, order, bn_ctx)
|
res = _lib.EC_GROUP_get_order(group, order, bn_ctx)
|
||||||
assert res == 1
|
backend.openssl_assert(res == 1)
|
||||||
|
|
||||||
order_bits = _lib.BN_num_bits(order)
|
order_bits = _lib.BN_num_bits(order)
|
||||||
|
|
||||||
if 8 * digest_len > order_bits:
|
return _truncate_digest(digest, order_bits)
|
||||||
digest_len = (order_bits + 7) // 8
|
|
||||||
digest = digest[:digest_len]
|
|
||||||
|
|
||||||
if 8 * digest_len > order_bits:
|
|
||||||
rshift = 8 - (order_bits & 0x7)
|
|
||||||
assert rshift > 0 and rshift < 8
|
|
||||||
|
|
||||||
mask = 0xFF >> rshift << rshift
|
|
||||||
|
|
||||||
# Set the bottom rshift bits to 0
|
|
||||||
digest = digest[:-1] + six.int2byte(six.indexbytes(digest, -1) & mask)
|
|
||||||
|
|
||||||
return digest
|
|
||||||
|
|
||||||
|
|
||||||
def _ec_key_curve_sn(backend, ec_key):
|
def _ec_key_curve_sn(backend, ec_key):
|
||||||
group = backend._lib.EC_KEY_get0_group(ec_key)
|
group = backend._lib.EC_KEY_get0_group(ec_key)
|
||||||
assert group != backend._ffi.NULL
|
backend.openssl_assert(group != backend._ffi.NULL)
|
||||||
|
|
||||||
nid = backend._lib.EC_GROUP_get_curve_name(group)
|
nid = backend._lib.EC_GROUP_get_curve_name(group)
|
||||||
assert nid != backend._lib.NID_undef
|
# The following check is to find EC keys with unnamed curves and raise
|
||||||
|
# an error for now.
|
||||||
|
if nid == backend._lib.NID_undef:
|
||||||
|
raise NotImplementedError(
|
||||||
|
"ECDSA certificates with unnamed curves are unsupported "
|
||||||
|
"at this time"
|
||||||
|
)
|
||||||
|
|
||||||
curve_name = backend._lib.OBJ_nid2sn(nid)
|
curve_name = backend._lib.OBJ_nid2sn(nid)
|
||||||
assert curve_name != backend._ffi.NULL
|
backend.openssl_assert(curve_name != backend._ffi.NULL)
|
||||||
|
|
||||||
sn = backend._ffi.string(curve_name).decode('ascii')
|
sn = backend._ffi.string(curve_name).decode('ascii')
|
||||||
return sn
|
return sn
|
||||||
|
|
||||||
|
|
||||||
|
def _mark_asn1_named_ec_curve(backend, ec_cdata):
|
||||||
|
"""
|
||||||
|
Set the named curve flag on the EC_KEY. This causes OpenSSL to
|
||||||
|
serialize EC keys along with their curve OID which makes
|
||||||
|
deserialization easier.
|
||||||
|
"""
|
||||||
|
|
||||||
|
backend._lib.EC_KEY_set_asn1_flag(
|
||||||
|
ec_cdata, backend._lib.OPENSSL_EC_NAMED_CURVE
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def _sn_to_elliptic_curve(backend, sn):
|
def _sn_to_elliptic_curve(backend, sn):
|
||||||
try:
|
try:
|
||||||
return ec._CURVE_TYPES[sn]()
|
return ec._CURVE_TYPES[sn]()
|
||||||
|
@ -87,7 +82,7 @@ def _sn_to_elliptic_curve(backend, sn):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@utils.register_interface(interfaces.AsymmetricSignatureContext)
|
@utils.register_interface(AsymmetricSignatureContext)
|
||||||
class _ECDSASignatureContext(object):
|
class _ECDSASignatureContext(object):
|
||||||
def __init__(self, backend, private_key, algorithm):
|
def __init__(self, backend, private_key, algorithm):
|
||||||
self._backend = backend
|
self._backend = backend
|
||||||
|
@ -105,7 +100,7 @@ class _ECDSASignatureContext(object):
|
||||||
digest = _truncate_digest_for_ecdsa(ec_key, digest, self._backend)
|
digest = _truncate_digest_for_ecdsa(ec_key, digest, self._backend)
|
||||||
|
|
||||||
max_size = self._backend._lib.ECDSA_size(ec_key)
|
max_size = self._backend._lib.ECDSA_size(ec_key)
|
||||||
assert max_size > 0
|
self._backend.openssl_assert(max_size > 0)
|
||||||
|
|
||||||
sigbuf = self._backend._ffi.new("char[]", max_size)
|
sigbuf = self._backend._ffi.new("char[]", max_size)
|
||||||
siglen_ptr = self._backend._ffi.new("unsigned int[]", 1)
|
siglen_ptr = self._backend._ffi.new("unsigned int[]", 1)
|
||||||
|
@ -117,11 +112,11 @@ class _ECDSASignatureContext(object):
|
||||||
siglen_ptr,
|
siglen_ptr,
|
||||||
ec_key
|
ec_key
|
||||||
)
|
)
|
||||||
assert res == 1
|
self._backend.openssl_assert(res == 1)
|
||||||
return self._backend._ffi.buffer(sigbuf)[:siglen_ptr[0]]
|
return self._backend._ffi.buffer(sigbuf)[:siglen_ptr[0]]
|
||||||
|
|
||||||
|
|
||||||
@utils.register_interface(interfaces.AsymmetricVerificationContext)
|
@utils.register_interface(AsymmetricVerificationContext)
|
||||||
class _ECDSAVerificationContext(object):
|
class _ECDSAVerificationContext(object):
|
||||||
def __init__(self, backend, public_key, signature, algorithm):
|
def __init__(self, backend, public_key, signature, algorithm):
|
||||||
self._backend = backend
|
self._backend = backend
|
||||||
|
@ -153,18 +148,18 @@ class _ECDSAVerificationContext(object):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
@utils.register_interface(interfaces.EllipticCurvePrivateKeyWithNumbers)
|
@utils.register_interface(ec.EllipticCurvePrivateKeyWithSerialization)
|
||||||
class _EllipticCurvePrivateKey(object):
|
class _EllipticCurvePrivateKey(object):
|
||||||
def __init__(self, backend, ec_key_cdata):
|
def __init__(self, backend, ec_key_cdata, evp_pkey):
|
||||||
self._backend = backend
|
self._backend = backend
|
||||||
|
_mark_asn1_named_ec_curve(backend, ec_key_cdata)
|
||||||
self._ec_key = ec_key_cdata
|
self._ec_key = ec_key_cdata
|
||||||
|
self._evp_pkey = evp_pkey
|
||||||
|
|
||||||
sn = _ec_key_curve_sn(backend, ec_key_cdata)
|
sn = _ec_key_curve_sn(backend, ec_key_cdata)
|
||||||
self._curve = _sn_to_elliptic_curve(backend, sn)
|
self._curve = _sn_to_elliptic_curve(backend, sn)
|
||||||
|
|
||||||
@property
|
curve = utils.read_only_property("_curve")
|
||||||
def curve(self):
|
|
||||||
return self._curve
|
|
||||||
|
|
||||||
def signer(self, signature_algorithm):
|
def signer(self, signature_algorithm):
|
||||||
if isinstance(signature_algorithm, ec.ECDSA):
|
if isinstance(signature_algorithm, ec.ECDSA):
|
||||||
|
@ -176,27 +171,52 @@ class _EllipticCurvePrivateKey(object):
|
||||||
"Unsupported elliptic curve signature algorithm.",
|
"Unsupported elliptic curve signature algorithm.",
|
||||||
_Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM)
|
_Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM)
|
||||||
|
|
||||||
|
def exchange(self, algorithm, peer_public_key):
|
||||||
|
if not (
|
||||||
|
self._backend.elliptic_curve_exchange_algorithm_supported(
|
||||||
|
algorithm, self.curve
|
||||||
|
)
|
||||||
|
):
|
||||||
|
raise UnsupportedAlgorithm(
|
||||||
|
"This backend does not support the ECDH algorithm.",
|
||||||
|
_Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM
|
||||||
|
)
|
||||||
|
|
||||||
|
group = self._backend._lib.EC_KEY_get0_group(self._ec_key)
|
||||||
|
z_len = (self._backend._lib.EC_GROUP_get_degree(group) + 7) // 8
|
||||||
|
self._backend.openssl_assert(z_len > 0)
|
||||||
|
z_buf = self._backend._ffi.new("uint8_t[]", z_len)
|
||||||
|
peer_key = self._backend._lib.EC_KEY_get0_public_key(
|
||||||
|
peer_public_key._ec_key
|
||||||
|
)
|
||||||
|
|
||||||
|
r = self._backend._lib.ECDH_compute_key(
|
||||||
|
z_buf, z_len, peer_key, self._ec_key, self._backend._ffi.NULL
|
||||||
|
)
|
||||||
|
self._backend.openssl_assert(r > 0)
|
||||||
|
return self._backend._ffi.buffer(z_buf)[:z_len]
|
||||||
|
|
||||||
def public_key(self):
|
def public_key(self):
|
||||||
group = self._backend._lib.EC_KEY_get0_group(self._ec_key)
|
group = self._backend._lib.EC_KEY_get0_group(self._ec_key)
|
||||||
assert group != self._backend._ffi.NULL
|
self._backend.openssl_assert(group != self._backend._ffi.NULL)
|
||||||
|
|
||||||
curve_nid = self._backend._lib.EC_GROUP_get_curve_name(group)
|
curve_nid = self._backend._lib.EC_GROUP_get_curve_name(group)
|
||||||
|
|
||||||
public_ec_key = self._backend._lib.EC_KEY_new_by_curve_name(curve_nid)
|
public_ec_key = self._backend._lib.EC_KEY_new_by_curve_name(curve_nid)
|
||||||
assert public_ec_key != self._backend._ffi.NULL
|
self._backend.openssl_assert(public_ec_key != self._backend._ffi.NULL)
|
||||||
public_ec_key = self._backend._ffi.gc(
|
public_ec_key = self._backend._ffi.gc(
|
||||||
public_ec_key, self._backend._lib.EC_KEY_free
|
public_ec_key, self._backend._lib.EC_KEY_free
|
||||||
)
|
)
|
||||||
|
|
||||||
point = self._backend._lib.EC_KEY_get0_public_key(self._ec_key)
|
point = self._backend._lib.EC_KEY_get0_public_key(self._ec_key)
|
||||||
assert point != self._backend._ffi.NULL
|
self._backend.openssl_assert(point != self._backend._ffi.NULL)
|
||||||
|
|
||||||
res = self._backend._lib.EC_KEY_set_public_key(public_ec_key, point)
|
res = self._backend._lib.EC_KEY_set_public_key(public_ec_key, point)
|
||||||
assert res == 1
|
self._backend.openssl_assert(res == 1)
|
||||||
|
|
||||||
return _EllipticCurvePublicKey(
|
evp_pkey = self._backend._ec_cdata_to_evp_pkey(public_ec_key)
|
||||||
self._backend, public_ec_key
|
|
||||||
)
|
return _EllipticCurvePublicKey(self._backend, public_ec_key, evp_pkey)
|
||||||
|
|
||||||
def private_numbers(self):
|
def private_numbers(self):
|
||||||
bn = self._backend._lib.EC_KEY_get0_private_key(self._ec_key)
|
bn = self._backend._lib.EC_KEY_get0_private_key(self._ec_key)
|
||||||
|
@ -206,21 +226,33 @@ class _EllipticCurvePrivateKey(object):
|
||||||
public_numbers=self.public_key().public_numbers()
|
public_numbers=self.public_key().public_numbers()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def private_bytes(self, encoding, format, encryption_algorithm):
|
||||||
|
return self._backend._private_key_bytes(
|
||||||
|
encoding,
|
||||||
|
format,
|
||||||
|
encryption_algorithm,
|
||||||
|
self._evp_pkey,
|
||||||
|
self._ec_key
|
||||||
|
)
|
||||||
|
|
||||||
@utils.register_interface(interfaces.EllipticCurvePublicKeyWithNumbers)
|
|
||||||
|
@utils.register_interface(ec.EllipticCurvePublicKeyWithSerialization)
|
||||||
class _EllipticCurvePublicKey(object):
|
class _EllipticCurvePublicKey(object):
|
||||||
def __init__(self, backend, ec_key_cdata):
|
def __init__(self, backend, ec_key_cdata, evp_pkey):
|
||||||
self._backend = backend
|
self._backend = backend
|
||||||
|
_mark_asn1_named_ec_curve(backend, ec_key_cdata)
|
||||||
self._ec_key = ec_key_cdata
|
self._ec_key = ec_key_cdata
|
||||||
|
self._evp_pkey = evp_pkey
|
||||||
|
|
||||||
sn = _ec_key_curve_sn(backend, ec_key_cdata)
|
sn = _ec_key_curve_sn(backend, ec_key_cdata)
|
||||||
self._curve = _sn_to_elliptic_curve(backend, sn)
|
self._curve = _sn_to_elliptic_curve(backend, sn)
|
||||||
|
|
||||||
@property
|
curve = utils.read_only_property("_curve")
|
||||||
def curve(self):
|
|
||||||
return self._curve
|
|
||||||
|
|
||||||
def verifier(self, signature, signature_algorithm):
|
def verifier(self, signature, signature_algorithm):
|
||||||
|
if not isinstance(signature, bytes):
|
||||||
|
raise TypeError("signature must be bytes.")
|
||||||
|
|
||||||
if isinstance(signature_algorithm, ec.ECDSA):
|
if isinstance(signature_algorithm, ec.ECDSA):
|
||||||
return _ECDSAVerificationContext(
|
return _ECDSAVerificationContext(
|
||||||
self._backend, self, signature, signature_algorithm.algorithm
|
self._backend, self, signature, signature_algorithm.algorithm
|
||||||
|
@ -235,14 +267,14 @@ class _EllipticCurvePublicKey(object):
|
||||||
self._backend._ec_key_determine_group_get_set_funcs(self._ec_key)
|
self._backend._ec_key_determine_group_get_set_funcs(self._ec_key)
|
||||||
)
|
)
|
||||||
point = self._backend._lib.EC_KEY_get0_public_key(self._ec_key)
|
point = self._backend._lib.EC_KEY_get0_public_key(self._ec_key)
|
||||||
assert point != self._backend._ffi.NULL
|
self._backend.openssl_assert(point != self._backend._ffi.NULL)
|
||||||
|
|
||||||
with self._backend._tmp_bn_ctx() as bn_ctx:
|
with self._backend._tmp_bn_ctx() as bn_ctx:
|
||||||
bn_x = self._backend._lib.BN_CTX_get(bn_ctx)
|
bn_x = self._backend._lib.BN_CTX_get(bn_ctx)
|
||||||
bn_y = self._backend._lib.BN_CTX_get(bn_ctx)
|
bn_y = self._backend._lib.BN_CTX_get(bn_ctx)
|
||||||
|
|
||||||
res = get_func(group, point, bn_x, bn_y, bn_ctx)
|
res = get_func(group, point, bn_x, bn_y, bn_ctx)
|
||||||
assert res == 1
|
self._backend.openssl_assert(res == 1)
|
||||||
|
|
||||||
x = self._backend._bn_to_int(bn_x)
|
x = self._backend._bn_to_int(bn_x)
|
||||||
y = self._backend._bn_to_int(bn_y)
|
y = self._backend._bn_to_int(bn_y)
|
||||||
|
@ -252,3 +284,16 @@ class _EllipticCurvePublicKey(object):
|
||||||
y=y,
|
y=y,
|
||||||
curve=self._curve
|
curve=self._curve
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def public_bytes(self, encoding, format):
|
||||||
|
if format is serialization.PublicFormat.PKCS1:
|
||||||
|
raise ValueError(
|
||||||
|
"EC public keys do not support PKCS1 serialization"
|
||||||
|
)
|
||||||
|
|
||||||
|
return self._backend._public_key_bytes(
|
||||||
|
encoding,
|
||||||
|
format,
|
||||||
|
self._evp_pkey,
|
||||||
|
None
|
||||||
|
)
|
||||||
|
|
|
@ -1,28 +1,19 @@
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# This file is dual licensed under the terms of the Apache License, Version
|
||||||
# you may not use this file except in compliance with the License.
|
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
|
||||||
# You may obtain a copy of the License at
|
# for complete details.
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
# implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
|
|
||||||
from cryptography import utils
|
from cryptography import utils
|
||||||
from cryptography.exceptions import UnsupportedAlgorithm, _Reasons
|
from cryptography.exceptions import UnsupportedAlgorithm, _Reasons
|
||||||
from cryptography.hazmat.primitives import interfaces
|
from cryptography.hazmat.primitives import hashes
|
||||||
|
|
||||||
|
|
||||||
@utils.register_interface(interfaces.HashContext)
|
@utils.register_interface(hashes.HashContext)
|
||||||
class _HashContext(object):
|
class _HashContext(object):
|
||||||
def __init__(self, backend, algorithm, ctx=None):
|
def __init__(self, backend, algorithm, ctx=None):
|
||||||
self.algorithm = algorithm
|
self._algorithm = algorithm
|
||||||
|
|
||||||
self._backend = backend
|
self._backend = backend
|
||||||
|
|
||||||
|
@ -40,30 +31,32 @@ class _HashContext(object):
|
||||||
)
|
)
|
||||||
res = self._backend._lib.EVP_DigestInit_ex(ctx, evp_md,
|
res = self._backend._lib.EVP_DigestInit_ex(ctx, evp_md,
|
||||||
self._backend._ffi.NULL)
|
self._backend._ffi.NULL)
|
||||||
assert res != 0
|
self._backend.openssl_assert(res != 0)
|
||||||
|
|
||||||
self._ctx = ctx
|
self._ctx = ctx
|
||||||
|
|
||||||
|
algorithm = utils.read_only_property("_algorithm")
|
||||||
|
|
||||||
def copy(self):
|
def copy(self):
|
||||||
copied_ctx = self._backend._lib.EVP_MD_CTX_create()
|
copied_ctx = self._backend._lib.EVP_MD_CTX_create()
|
||||||
copied_ctx = self._backend._ffi.gc(
|
copied_ctx = self._backend._ffi.gc(
|
||||||
copied_ctx, self._backend._lib.EVP_MD_CTX_destroy
|
copied_ctx, self._backend._lib.EVP_MD_CTX_destroy
|
||||||
)
|
)
|
||||||
res = self._backend._lib.EVP_MD_CTX_copy_ex(copied_ctx, self._ctx)
|
res = self._backend._lib.EVP_MD_CTX_copy_ex(copied_ctx, self._ctx)
|
||||||
assert res != 0
|
self._backend.openssl_assert(res != 0)
|
||||||
return _HashContext(self._backend, self.algorithm, ctx=copied_ctx)
|
return _HashContext(self._backend, self.algorithm, ctx=copied_ctx)
|
||||||
|
|
||||||
def update(self, data):
|
def update(self, data):
|
||||||
res = self._backend._lib.EVP_DigestUpdate(self._ctx, data, len(data))
|
res = self._backend._lib.EVP_DigestUpdate(self._ctx, data, len(data))
|
||||||
assert res != 0
|
self._backend.openssl_assert(res != 0)
|
||||||
|
|
||||||
def finalize(self):
|
def finalize(self):
|
||||||
buf = self._backend._ffi.new("unsigned char[]",
|
buf = self._backend._ffi.new("unsigned char[]",
|
||||||
self._backend._lib.EVP_MAX_MD_SIZE)
|
self._backend._lib.EVP_MAX_MD_SIZE)
|
||||||
outlen = self._backend._ffi.new("unsigned int *")
|
outlen = self._backend._ffi.new("unsigned int *")
|
||||||
res = self._backend._lib.EVP_DigestFinal_ex(self._ctx, buf, outlen)
|
res = self._backend._lib.EVP_DigestFinal_ex(self._ctx, buf, outlen)
|
||||||
assert res != 0
|
self._backend.openssl_assert(res != 0)
|
||||||
assert outlen[0] == self.algorithm.digest_size
|
self._backend.openssl_assert(outlen[0] == self.algorithm.digest_size)
|
||||||
res = self._backend._lib.EVP_MD_CTX_cleanup(self._ctx)
|
res = self._backend._lib.EVP_MD_CTX_cleanup(self._ctx)
|
||||||
assert res == 1
|
self._backend.openssl_assert(res == 1)
|
||||||
return self._backend._ffi.buffer(buf)[:outlen[0]]
|
return self._backend._ffi.buffer(buf)[:outlen[0]]
|
||||||
|
|
|
@ -1,28 +1,22 @@
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# This file is dual licensed under the terms of the Apache License, Version
|
||||||
# you may not use this file except in compliance with the License.
|
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
|
||||||
# You may obtain a copy of the License at
|
# for complete details.
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
# implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
|
|
||||||
from cryptography import utils
|
from cryptography import utils
|
||||||
from cryptography.exceptions import UnsupportedAlgorithm, _Reasons
|
from cryptography.exceptions import (
|
||||||
from cryptography.hazmat.primitives import interfaces
|
InvalidSignature, UnsupportedAlgorithm, _Reasons
|
||||||
|
)
|
||||||
|
from cryptography.hazmat.primitives import constant_time, hashes, interfaces
|
||||||
|
|
||||||
|
|
||||||
@utils.register_interface(interfaces.HashContext)
|
@utils.register_interface(interfaces.MACContext)
|
||||||
|
@utils.register_interface(hashes.HashContext)
|
||||||
class _HMACContext(object):
|
class _HMACContext(object):
|
||||||
def __init__(self, backend, key, algorithm, ctx=None):
|
def __init__(self, backend, key, algorithm, ctx=None):
|
||||||
self.algorithm = algorithm
|
self._algorithm = algorithm
|
||||||
self._backend = backend
|
self._backend = backend
|
||||||
|
|
||||||
if ctx is None:
|
if ctx is None:
|
||||||
|
@ -42,11 +36,13 @@ class _HMACContext(object):
|
||||||
res = self._backend._lib.Cryptography_HMAC_Init_ex(
|
res = self._backend._lib.Cryptography_HMAC_Init_ex(
|
||||||
ctx, key, len(key), evp_md, self._backend._ffi.NULL
|
ctx, key, len(key), evp_md, self._backend._ffi.NULL
|
||||||
)
|
)
|
||||||
assert res != 0
|
self._backend.openssl_assert(res != 0)
|
||||||
|
|
||||||
self._ctx = ctx
|
self._ctx = ctx
|
||||||
self._key = key
|
self._key = key
|
||||||
|
|
||||||
|
algorithm = utils.read_only_property("_algorithm")
|
||||||
|
|
||||||
def copy(self):
|
def copy(self):
|
||||||
copied_ctx = self._backend._ffi.new("HMAC_CTX *")
|
copied_ctx = self._backend._ffi.new("HMAC_CTX *")
|
||||||
self._backend._lib.HMAC_CTX_init(copied_ctx)
|
self._backend._lib.HMAC_CTX_init(copied_ctx)
|
||||||
|
@ -56,7 +52,7 @@ class _HMACContext(object):
|
||||||
res = self._backend._lib.Cryptography_HMAC_CTX_copy(
|
res = self._backend._lib.Cryptography_HMAC_CTX_copy(
|
||||||
copied_ctx, self._ctx
|
copied_ctx, self._ctx
|
||||||
)
|
)
|
||||||
assert res != 0
|
self._backend.openssl_assert(res != 0)
|
||||||
return _HMACContext(
|
return _HMACContext(
|
||||||
self._backend, self._key, self.algorithm, ctx=copied_ctx
|
self._backend, self._key, self.algorithm, ctx=copied_ctx
|
||||||
)
|
)
|
||||||
|
@ -65,7 +61,7 @@ class _HMACContext(object):
|
||||||
res = self._backend._lib.Cryptography_HMAC_Update(
|
res = self._backend._lib.Cryptography_HMAC_Update(
|
||||||
self._ctx, data, len(data)
|
self._ctx, data, len(data)
|
||||||
)
|
)
|
||||||
assert res != 0
|
self._backend.openssl_assert(res != 0)
|
||||||
|
|
||||||
def finalize(self):
|
def finalize(self):
|
||||||
buf = self._backend._ffi.new("unsigned char[]",
|
buf = self._backend._ffi.new("unsigned char[]",
|
||||||
|
@ -74,7 +70,12 @@ class _HMACContext(object):
|
||||||
res = self._backend._lib.Cryptography_HMAC_Final(
|
res = self._backend._lib.Cryptography_HMAC_Final(
|
||||||
self._ctx, buf, outlen
|
self._ctx, buf, outlen
|
||||||
)
|
)
|
||||||
assert res != 0
|
self._backend.openssl_assert(res != 0)
|
||||||
assert outlen[0] == self.algorithm.digest_size
|
self._backend.openssl_assert(outlen[0] == self.algorithm.digest_size)
|
||||||
self._backend._lib.HMAC_CTX_cleanup(self._ctx)
|
self._backend._lib.HMAC_CTX_cleanup(self._ctx)
|
||||||
return self._backend._ffi.buffer(buf)[:outlen[0]]
|
return self._backend._ffi.buffer(buf)[:outlen[0]]
|
||||||
|
|
||||||
|
def verify(self, signature):
|
||||||
|
digest = self.finalize()
|
||||||
|
if not constant_time.bytes_eq(digest, signature):
|
||||||
|
raise InvalidSignature("Signature did not match digest.")
|
||||||
|
|
|
@ -1,15 +1,6 @@
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# This file is dual licensed under the terms of the Apache License, Version
|
||||||
# you may not use this file except in compliance with the License.
|
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
|
||||||
# You may obtain a copy of the License at
|
# for complete details.
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
# implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
|
@ -19,13 +10,15 @@ from cryptography import utils
|
||||||
from cryptography.exceptions import (
|
from cryptography.exceptions import (
|
||||||
AlreadyFinalized, InvalidSignature, UnsupportedAlgorithm, _Reasons
|
AlreadyFinalized, InvalidSignature, UnsupportedAlgorithm, _Reasons
|
||||||
)
|
)
|
||||||
from cryptography.hazmat.primitives import hashes, interfaces
|
from cryptography.hazmat.primitives import hashes
|
||||||
from cryptography.hazmat.primitives.asymmetric import rsa
|
from cryptography.hazmat.primitives.asymmetric import (
|
||||||
from cryptography.hazmat.primitives.asymmetric.padding import (
|
AsymmetricSignatureContext, AsymmetricVerificationContext, rsa
|
||||||
MGF1, OAEP, PKCS1v15, PSS
|
|
||||||
)
|
)
|
||||||
from cryptography.hazmat.primitives.interfaces import (
|
from cryptography.hazmat.primitives.asymmetric.padding import (
|
||||||
RSAPrivateKeyWithNumbers, RSAPublicKeyWithNumbers
|
AsymmetricPadding, MGF1, OAEP, PKCS1v15, PSS
|
||||||
|
)
|
||||||
|
from cryptography.hazmat.primitives.asymmetric.rsa import (
|
||||||
|
RSAPrivateKeyWithSerialization, RSAPublicKeyWithSerialization
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -43,7 +36,7 @@ def _get_rsa_pss_salt_length(pss, key_size, digest_size):
|
||||||
|
|
||||||
|
|
||||||
def _enc_dec_rsa(backend, key, data, padding):
|
def _enc_dec_rsa(backend, key, data, padding):
|
||||||
if not isinstance(padding, interfaces.AsymmetricPadding):
|
if not isinstance(padding, AsymmetricPadding):
|
||||||
raise TypeError("Padding must be an instance of AsymmetricPadding.")
|
raise TypeError("Padding must be an instance of AsymmetricPadding.")
|
||||||
|
|
||||||
if isinstance(padding, PKCS1v15):
|
if isinstance(padding, PKCS1v15):
|
||||||
|
@ -96,15 +89,15 @@ def _enc_dec_rsa_pkey_ctx(backend, key, data, padding_enum):
|
||||||
pkey_ctx = backend._lib.EVP_PKEY_CTX_new(
|
pkey_ctx = backend._lib.EVP_PKEY_CTX_new(
|
||||||
key._evp_pkey, backend._ffi.NULL
|
key._evp_pkey, backend._ffi.NULL
|
||||||
)
|
)
|
||||||
assert pkey_ctx != backend._ffi.NULL
|
backend.openssl_assert(pkey_ctx != backend._ffi.NULL)
|
||||||
pkey_ctx = backend._ffi.gc(pkey_ctx, backend._lib.EVP_PKEY_CTX_free)
|
pkey_ctx = backend._ffi.gc(pkey_ctx, backend._lib.EVP_PKEY_CTX_free)
|
||||||
res = init(pkey_ctx)
|
res = init(pkey_ctx)
|
||||||
assert res == 1
|
backend.openssl_assert(res == 1)
|
||||||
res = backend._lib.EVP_PKEY_CTX_set_rsa_padding(
|
res = backend._lib.EVP_PKEY_CTX_set_rsa_padding(
|
||||||
pkey_ctx, padding_enum)
|
pkey_ctx, padding_enum)
|
||||||
assert res > 0
|
backend.openssl_assert(res > 0)
|
||||||
buf_size = backend._lib.EVP_PKEY_size(key._evp_pkey)
|
buf_size = backend._lib.EVP_PKEY_size(key._evp_pkey)
|
||||||
assert buf_size > 0
|
backend.openssl_assert(buf_size > 0)
|
||||||
outlen = backend._ffi.new("size_t *", buf_size)
|
outlen = backend._ffi.new("size_t *", buf_size)
|
||||||
buf = backend._ffi.new("char[]", buf_size)
|
buf = backend._ffi.new("char[]", buf_size)
|
||||||
res = crypt(pkey_ctx, buf, outlen, data, len(data))
|
res = crypt(pkey_ctx, buf, outlen, data, len(data))
|
||||||
|
@ -121,7 +114,7 @@ def _enc_dec_rsa_098(backend, key, data, padding_enum):
|
||||||
crypt = backend._lib.RSA_private_decrypt
|
crypt = backend._lib.RSA_private_decrypt
|
||||||
|
|
||||||
key_size = backend._lib.RSA_size(key._rsa_cdata)
|
key_size = backend._lib.RSA_size(key._rsa_cdata)
|
||||||
assert key_size > 0
|
backend.openssl_assert(key_size > 0)
|
||||||
buf = backend._ffi.new("unsigned char[]", key_size)
|
buf = backend._ffi.new("unsigned char[]", key_size)
|
||||||
res = crypt(len(data), data, buf, key._rsa_cdata, padding_enum)
|
res = crypt(len(data), data, buf, key._rsa_cdata, padding_enum)
|
||||||
if res < 0:
|
if res < 0:
|
||||||
|
@ -142,26 +135,30 @@ def _handle_rsa_enc_dec_error(backend, key):
|
||||||
"larger key size."
|
"larger key size."
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
assert (
|
decoding_errors = [
|
||||||
errors[0].reason == backend._lib.RSA_R_BLOCK_TYPE_IS_NOT_01 or
|
backend._lib.RSA_R_BLOCK_TYPE_IS_NOT_01,
|
||||||
errors[0].reason == backend._lib.RSA_R_BLOCK_TYPE_IS_NOT_02
|
backend._lib.RSA_R_BLOCK_TYPE_IS_NOT_02,
|
||||||
)
|
]
|
||||||
|
if backend._lib.Cryptography_HAS_RSA_R_PKCS_DECODING_ERROR:
|
||||||
|
decoding_errors.append(backend._lib.RSA_R_PKCS_DECODING_ERROR)
|
||||||
|
|
||||||
|
assert errors[0].reason in decoding_errors
|
||||||
raise ValueError("Decryption failed.")
|
raise ValueError("Decryption failed.")
|
||||||
|
|
||||||
|
|
||||||
@utils.register_interface(interfaces.AsymmetricSignatureContext)
|
@utils.register_interface(AsymmetricSignatureContext)
|
||||||
class _RSASignatureContext(object):
|
class _RSASignatureContext(object):
|
||||||
def __init__(self, backend, private_key, padding, algorithm):
|
def __init__(self, backend, private_key, padding, algorithm):
|
||||||
self._backend = backend
|
self._backend = backend
|
||||||
self._private_key = private_key
|
self._private_key = private_key
|
||||||
|
|
||||||
if not isinstance(padding, interfaces.AsymmetricPadding):
|
if not isinstance(padding, AsymmetricPadding):
|
||||||
raise TypeError(
|
raise TypeError("Expected provider of AsymmetricPadding.")
|
||||||
"Expected provider of interfaces.AsymmetricPadding.")
|
|
||||||
|
|
||||||
self._pkey_size = self._backend._lib.EVP_PKEY_size(
|
self._pkey_size = self._backend._lib.EVP_PKEY_size(
|
||||||
self._private_key._evp_pkey
|
self._private_key._evp_pkey
|
||||||
)
|
)
|
||||||
|
self._backend.openssl_assert(self._pkey_size > 0)
|
||||||
|
|
||||||
if isinstance(padding, PKCS1v15):
|
if isinstance(padding, PKCS1v15):
|
||||||
if self._backend._lib.Cryptography_HAS_PKEY_CTX:
|
if self._backend._lib.Cryptography_HAS_PKEY_CTX:
|
||||||
|
@ -178,7 +175,6 @@ class _RSASignatureContext(object):
|
||||||
|
|
||||||
# Size of key in bytes - 2 is the maximum
|
# Size of key in bytes - 2 is the maximum
|
||||||
# PSS signature length (salt length is checked later)
|
# PSS signature length (salt length is checked later)
|
||||||
assert self._pkey_size > 0
|
|
||||||
if self._pkey_size - algorithm.digest_size - 2 < 0:
|
if self._pkey_size - algorithm.digest_size - 2 < 0:
|
||||||
raise ValueError("Digest too large for key size. Use a larger "
|
raise ValueError("Digest too large for key size. Use a larger "
|
||||||
"key.")
|
"key.")
|
||||||
|
@ -211,7 +207,7 @@ class _RSASignatureContext(object):
|
||||||
def finalize(self):
|
def finalize(self):
|
||||||
evp_md = self._backend._lib.EVP_get_digestbyname(
|
evp_md = self._backend._lib.EVP_get_digestbyname(
|
||||||
self._algorithm.name.encode("ascii"))
|
self._algorithm.name.encode("ascii"))
|
||||||
assert evp_md != self._backend._ffi.NULL
|
self._backend.openssl_assert(evp_md != self._backend._ffi.NULL)
|
||||||
|
|
||||||
return self._finalize_method(evp_md)
|
return self._finalize_method(evp_md)
|
||||||
|
|
||||||
|
@ -219,18 +215,18 @@ class _RSASignatureContext(object):
|
||||||
pkey_ctx = self._backend._lib.EVP_PKEY_CTX_new(
|
pkey_ctx = self._backend._lib.EVP_PKEY_CTX_new(
|
||||||
self._private_key._evp_pkey, self._backend._ffi.NULL
|
self._private_key._evp_pkey, self._backend._ffi.NULL
|
||||||
)
|
)
|
||||||
assert pkey_ctx != self._backend._ffi.NULL
|
self._backend.openssl_assert(pkey_ctx != self._backend._ffi.NULL)
|
||||||
pkey_ctx = self._backend._ffi.gc(pkey_ctx,
|
pkey_ctx = self._backend._ffi.gc(pkey_ctx,
|
||||||
self._backend._lib.EVP_PKEY_CTX_free)
|
self._backend._lib.EVP_PKEY_CTX_free)
|
||||||
res = self._backend._lib.EVP_PKEY_sign_init(pkey_ctx)
|
res = self._backend._lib.EVP_PKEY_sign_init(pkey_ctx)
|
||||||
assert res == 1
|
self._backend.openssl_assert(res == 1)
|
||||||
res = self._backend._lib.EVP_PKEY_CTX_set_signature_md(
|
res = self._backend._lib.EVP_PKEY_CTX_set_signature_md(
|
||||||
pkey_ctx, evp_md)
|
pkey_ctx, evp_md)
|
||||||
assert res > 0
|
self._backend.openssl_assert(res > 0)
|
||||||
|
|
||||||
res = self._backend._lib.EVP_PKEY_CTX_set_rsa_padding(
|
res = self._backend._lib.EVP_PKEY_CTX_set_rsa_padding(
|
||||||
pkey_ctx, self._padding_enum)
|
pkey_ctx, self._padding_enum)
|
||||||
assert res > 0
|
self._backend.openssl_assert(res > 0)
|
||||||
if isinstance(self._padding, PSS):
|
if isinstance(self._padding, PSS):
|
||||||
res = self._backend._lib.EVP_PKEY_CTX_set_rsa_pss_saltlen(
|
res = self._backend._lib.EVP_PKEY_CTX_set_rsa_pss_saltlen(
|
||||||
pkey_ctx,
|
pkey_ctx,
|
||||||
|
@ -240,17 +236,19 @@ class _RSASignatureContext(object):
|
||||||
self._hash_ctx.algorithm.digest_size
|
self._hash_ctx.algorithm.digest_size
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
assert res > 0
|
self._backend.openssl_assert(res > 0)
|
||||||
|
|
||||||
if self._backend._lib.Cryptography_HAS_MGF1_MD:
|
if self._backend._lib.Cryptography_HAS_MGF1_MD:
|
||||||
# MGF1 MD is configurable in OpenSSL 1.0.1+
|
# MGF1 MD is configurable in OpenSSL 1.0.1+
|
||||||
mgf1_md = self._backend._lib.EVP_get_digestbyname(
|
mgf1_md = self._backend._lib.EVP_get_digestbyname(
|
||||||
self._padding._mgf._algorithm.name.encode("ascii"))
|
self._padding._mgf._algorithm.name.encode("ascii"))
|
||||||
assert mgf1_md != self._backend._ffi.NULL
|
self._backend.openssl_assert(
|
||||||
|
mgf1_md != self._backend._ffi.NULL
|
||||||
|
)
|
||||||
res = self._backend._lib.EVP_PKEY_CTX_set_rsa_mgf1_md(
|
res = self._backend._lib.EVP_PKEY_CTX_set_rsa_mgf1_md(
|
||||||
pkey_ctx, mgf1_md
|
pkey_ctx, mgf1_md
|
||||||
)
|
)
|
||||||
assert res > 0
|
self._backend.openssl_assert(res > 0)
|
||||||
data_to_sign = self._hash_ctx.finalize()
|
data_to_sign = self._hash_ctx.finalize()
|
||||||
buflen = self._backend._ffi.new("size_t *")
|
buflen = self._backend._ffi.new("size_t *")
|
||||||
res = self._backend._lib.EVP_PKEY_sign(
|
res = self._backend._lib.EVP_PKEY_sign(
|
||||||
|
@ -260,7 +258,7 @@ class _RSASignatureContext(object):
|
||||||
data_to_sign,
|
data_to_sign,
|
||||||
len(data_to_sign)
|
len(data_to_sign)
|
||||||
)
|
)
|
||||||
assert res == 1
|
self._backend.openssl_assert(res == 1)
|
||||||
buf = self._backend._ffi.new("unsigned char[]", buflen[0])
|
buf = self._backend._ffi.new("unsigned char[]", buflen[0])
|
||||||
res = self._backend._lib.EVP_PKEY_sign(
|
res = self._backend._lib.EVP_PKEY_sign(
|
||||||
pkey_ctx, buf, buflen, data_to_sign, len(data_to_sign))
|
pkey_ctx, buf, buflen, data_to_sign, len(data_to_sign))
|
||||||
|
@ -272,8 +270,9 @@ class _RSASignatureContext(object):
|
||||||
self._backend._lib.RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE):
|
self._backend._lib.RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE):
|
||||||
reason = ("Salt length too long for key size. Try using "
|
reason = ("Salt length too long for key size. Try using "
|
||||||
"MAX_LENGTH instead.")
|
"MAX_LENGTH instead.")
|
||||||
elif (errors[0].reason ==
|
else:
|
||||||
self._backend._lib.RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY):
|
assert (errors[0].reason ==
|
||||||
|
self._backend._lib.RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY)
|
||||||
reason = "Digest too large for key size. Use a larger key."
|
reason = "Digest too large for key size. Use a larger key."
|
||||||
assert reason is not None
|
assert reason is not None
|
||||||
raise ValueError(reason)
|
raise ValueError(reason)
|
||||||
|
@ -333,24 +332,24 @@ class _RSASignatureContext(object):
|
||||||
self._private_key._rsa_cdata,
|
self._private_key._rsa_cdata,
|
||||||
self._backend._lib.RSA_NO_PADDING
|
self._backend._lib.RSA_NO_PADDING
|
||||||
)
|
)
|
||||||
assert sig_len != -1
|
self._backend.openssl_assert(sig_len != -1)
|
||||||
return self._backend._ffi.buffer(sig_buf)[:sig_len]
|
return self._backend._ffi.buffer(sig_buf)[:sig_len]
|
||||||
|
|
||||||
|
|
||||||
@utils.register_interface(interfaces.AsymmetricVerificationContext)
|
@utils.register_interface(AsymmetricVerificationContext)
|
||||||
class _RSAVerificationContext(object):
|
class _RSAVerificationContext(object):
|
||||||
def __init__(self, backend, public_key, signature, padding, algorithm):
|
def __init__(self, backend, public_key, signature, padding, algorithm):
|
||||||
self._backend = backend
|
self._backend = backend
|
||||||
self._public_key = public_key
|
self._public_key = public_key
|
||||||
self._signature = signature
|
self._signature = signature
|
||||||
|
|
||||||
if not isinstance(padding, interfaces.AsymmetricPadding):
|
if not isinstance(padding, AsymmetricPadding):
|
||||||
raise TypeError(
|
raise TypeError("Expected provider of AsymmetricPadding.")
|
||||||
"Expected provider of interfaces.AsymmetricPadding.")
|
|
||||||
|
|
||||||
self._pkey_size = self._backend._lib.EVP_PKEY_size(
|
self._pkey_size = self._backend._lib.EVP_PKEY_size(
|
||||||
self._public_key._evp_pkey
|
self._public_key._evp_pkey
|
||||||
)
|
)
|
||||||
|
self._backend.openssl_assert(self._pkey_size > 0)
|
||||||
|
|
||||||
if isinstance(padding, PKCS1v15):
|
if isinstance(padding, PKCS1v15):
|
||||||
if self._backend._lib.Cryptography_HAS_PKEY_CTX:
|
if self._backend._lib.Cryptography_HAS_PKEY_CTX:
|
||||||
|
@ -367,7 +366,6 @@ class _RSAVerificationContext(object):
|
||||||
|
|
||||||
# Size of key in bytes - 2 is the maximum
|
# Size of key in bytes - 2 is the maximum
|
||||||
# PSS signature length (salt length is checked later)
|
# PSS signature length (salt length is checked later)
|
||||||
assert self._pkey_size > 0
|
|
||||||
if self._pkey_size - algorithm.digest_size - 2 < 0:
|
if self._pkey_size - algorithm.digest_size - 2 < 0:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"Digest too large for key size. Check that you have the "
|
"Digest too large for key size. Check that you have the "
|
||||||
|
@ -402,7 +400,7 @@ class _RSAVerificationContext(object):
|
||||||
def verify(self):
|
def verify(self):
|
||||||
evp_md = self._backend._lib.EVP_get_digestbyname(
|
evp_md = self._backend._lib.EVP_get_digestbyname(
|
||||||
self._algorithm.name.encode("ascii"))
|
self._algorithm.name.encode("ascii"))
|
||||||
assert evp_md != self._backend._ffi.NULL
|
self._backend.openssl_assert(evp_md != self._backend._ffi.NULL)
|
||||||
|
|
||||||
self._verify_method(evp_md)
|
self._verify_method(evp_md)
|
||||||
|
|
||||||
|
@ -410,18 +408,18 @@ class _RSAVerificationContext(object):
|
||||||
pkey_ctx = self._backend._lib.EVP_PKEY_CTX_new(
|
pkey_ctx = self._backend._lib.EVP_PKEY_CTX_new(
|
||||||
self._public_key._evp_pkey, self._backend._ffi.NULL
|
self._public_key._evp_pkey, self._backend._ffi.NULL
|
||||||
)
|
)
|
||||||
assert pkey_ctx != self._backend._ffi.NULL
|
self._backend.openssl_assert(pkey_ctx != self._backend._ffi.NULL)
|
||||||
pkey_ctx = self._backend._ffi.gc(pkey_ctx,
|
pkey_ctx = self._backend._ffi.gc(pkey_ctx,
|
||||||
self._backend._lib.EVP_PKEY_CTX_free)
|
self._backend._lib.EVP_PKEY_CTX_free)
|
||||||
res = self._backend._lib.EVP_PKEY_verify_init(pkey_ctx)
|
res = self._backend._lib.EVP_PKEY_verify_init(pkey_ctx)
|
||||||
assert res == 1
|
self._backend.openssl_assert(res == 1)
|
||||||
res = self._backend._lib.EVP_PKEY_CTX_set_signature_md(
|
res = self._backend._lib.EVP_PKEY_CTX_set_signature_md(
|
||||||
pkey_ctx, evp_md)
|
pkey_ctx, evp_md)
|
||||||
assert res > 0
|
self._backend.openssl_assert(res > 0)
|
||||||
|
|
||||||
res = self._backend._lib.EVP_PKEY_CTX_set_rsa_padding(
|
res = self._backend._lib.EVP_PKEY_CTX_set_rsa_padding(
|
||||||
pkey_ctx, self._padding_enum)
|
pkey_ctx, self._padding_enum)
|
||||||
assert res > 0
|
self._backend.openssl_assert(res > 0)
|
||||||
if isinstance(self._padding, PSS):
|
if isinstance(self._padding, PSS):
|
||||||
res = self._backend._lib.EVP_PKEY_CTX_set_rsa_pss_saltlen(
|
res = self._backend._lib.EVP_PKEY_CTX_set_rsa_pss_saltlen(
|
||||||
pkey_ctx,
|
pkey_ctx,
|
||||||
|
@ -431,16 +429,18 @@ class _RSAVerificationContext(object):
|
||||||
self._hash_ctx.algorithm.digest_size
|
self._hash_ctx.algorithm.digest_size
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
assert res > 0
|
self._backend.openssl_assert(res > 0)
|
||||||
if self._backend._lib.Cryptography_HAS_MGF1_MD:
|
if self._backend._lib.Cryptography_HAS_MGF1_MD:
|
||||||
# MGF1 MD is configurable in OpenSSL 1.0.1+
|
# MGF1 MD is configurable in OpenSSL 1.0.1+
|
||||||
mgf1_md = self._backend._lib.EVP_get_digestbyname(
|
mgf1_md = self._backend._lib.EVP_get_digestbyname(
|
||||||
self._padding._mgf._algorithm.name.encode("ascii"))
|
self._padding._mgf._algorithm.name.encode("ascii"))
|
||||||
assert mgf1_md != self._backend._ffi.NULL
|
self._backend.openssl_assert(
|
||||||
|
mgf1_md != self._backend._ffi.NULL
|
||||||
|
)
|
||||||
res = self._backend._lib.EVP_PKEY_CTX_set_rsa_mgf1_md(
|
res = self._backend._lib.EVP_PKEY_CTX_set_rsa_mgf1_md(
|
||||||
pkey_ctx, mgf1_md
|
pkey_ctx, mgf1_md
|
||||||
)
|
)
|
||||||
assert res > 0
|
self._backend.openssl_assert(res > 0)
|
||||||
|
|
||||||
data_to_verify = self._hash_ctx.finalize()
|
data_to_verify = self._hash_ctx.finalize()
|
||||||
res = self._backend._lib.EVP_PKEY_verify(
|
res = self._backend._lib.EVP_PKEY_verify(
|
||||||
|
@ -453,7 +453,7 @@ class _RSAVerificationContext(object):
|
||||||
# The previous call can return negative numbers in the event of an
|
# The previous call can return negative numbers in the event of an
|
||||||
# error. This is not a signature failure but we need to fail if it
|
# error. This is not a signature failure but we need to fail if it
|
||||||
# occurs.
|
# occurs.
|
||||||
assert res >= 0
|
self._backend.openssl_assert(res >= 0)
|
||||||
if res == 0:
|
if res == 0:
|
||||||
errors = self._backend._consume_errors()
|
errors = self._backend._consume_errors()
|
||||||
assert errors
|
assert errors
|
||||||
|
@ -473,7 +473,7 @@ class _RSAVerificationContext(object):
|
||||||
# The previous call can return negative numbers in the event of an
|
# The previous call can return negative numbers in the event of an
|
||||||
# error. This is not a signature failure but we need to fail if it
|
# error. This is not a signature failure but we need to fail if it
|
||||||
# occurs.
|
# occurs.
|
||||||
assert res >= 0
|
self._backend.openssl_assert(res >= 0)
|
||||||
if res == 0:
|
if res == 0:
|
||||||
errors = self._backend._consume_errors()
|
errors = self._backend._consume_errors()
|
||||||
assert errors
|
assert errors
|
||||||
|
@ -511,26 +511,16 @@ class _RSAVerificationContext(object):
|
||||||
raise InvalidSignature
|
raise InvalidSignature
|
||||||
|
|
||||||
|
|
||||||
@utils.register_interface(RSAPrivateKeyWithNumbers)
|
@utils.register_interface(RSAPrivateKeyWithSerialization)
|
||||||
class _RSAPrivateKey(object):
|
class _RSAPrivateKey(object):
|
||||||
def __init__(self, backend, rsa_cdata):
|
def __init__(self, backend, rsa_cdata, evp_pkey):
|
||||||
self._backend = backend
|
self._backend = backend
|
||||||
self._rsa_cdata = rsa_cdata
|
self._rsa_cdata = rsa_cdata
|
||||||
|
|
||||||
evp_pkey = self._backend._lib.EVP_PKEY_new()
|
|
||||||
assert evp_pkey != self._backend._ffi.NULL
|
|
||||||
evp_pkey = self._backend._ffi.gc(
|
|
||||||
evp_pkey, self._backend._lib.EVP_PKEY_free
|
|
||||||
)
|
|
||||||
res = self._backend._lib.EVP_PKEY_set1_RSA(evp_pkey, rsa_cdata)
|
|
||||||
assert res == 1
|
|
||||||
self._evp_pkey = evp_pkey
|
self._evp_pkey = evp_pkey
|
||||||
|
|
||||||
self._key_size = self._backend._lib.BN_num_bits(self._rsa_cdata.n)
|
self._key_size = self._backend._lib.BN_num_bits(self._rsa_cdata.n)
|
||||||
|
|
||||||
@property
|
key_size = utils.read_only_property("_key_size")
|
||||||
def key_size(self):
|
|
||||||
return self._key_size
|
|
||||||
|
|
||||||
def signer(self, padding, algorithm):
|
def signer(self, padding, algorithm):
|
||||||
return _RSASignatureContext(self._backend, self, padding, algorithm)
|
return _RSASignatureContext(self._backend, self, padding, algorithm)
|
||||||
|
@ -544,13 +534,14 @@ class _RSAPrivateKey(object):
|
||||||
|
|
||||||
def public_key(self):
|
def public_key(self):
|
||||||
ctx = self._backend._lib.RSA_new()
|
ctx = self._backend._lib.RSA_new()
|
||||||
assert ctx != self._backend._ffi.NULL
|
self._backend.openssl_assert(ctx != self._backend._ffi.NULL)
|
||||||
ctx = self._backend._ffi.gc(ctx, self._backend._lib.RSA_free)
|
ctx = self._backend._ffi.gc(ctx, self._backend._lib.RSA_free)
|
||||||
ctx.e = self._backend._lib.BN_dup(self._rsa_cdata.e)
|
ctx.e = self._backend._lib.BN_dup(self._rsa_cdata.e)
|
||||||
ctx.n = self._backend._lib.BN_dup(self._rsa_cdata.n)
|
ctx.n = self._backend._lib.BN_dup(self._rsa_cdata.n)
|
||||||
res = self._backend._lib.RSA_blinding_on(ctx, self._backend._ffi.NULL)
|
res = self._backend._lib.RSA_blinding_on(ctx, self._backend._ffi.NULL)
|
||||||
assert res == 1
|
self._backend.openssl_assert(res == 1)
|
||||||
return _RSAPublicKey(self._backend, ctx)
|
evp_pkey = self._backend._rsa_cdata_to_evp_pkey(ctx)
|
||||||
|
return _RSAPublicKey(self._backend, ctx, evp_pkey)
|
||||||
|
|
||||||
def private_numbers(self):
|
def private_numbers(self):
|
||||||
return rsa.RSAPrivateNumbers(
|
return rsa.RSAPrivateNumbers(
|
||||||
|
@ -566,29 +557,31 @@ class _RSAPrivateKey(object):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def private_bytes(self, encoding, format, encryption_algorithm):
|
||||||
|
return self._backend._private_key_bytes(
|
||||||
|
encoding,
|
||||||
|
format,
|
||||||
|
encryption_algorithm,
|
||||||
|
self._evp_pkey,
|
||||||
|
self._rsa_cdata
|
||||||
|
)
|
||||||
|
|
||||||
@utils.register_interface(RSAPublicKeyWithNumbers)
|
|
||||||
|
@utils.register_interface(RSAPublicKeyWithSerialization)
|
||||||
class _RSAPublicKey(object):
|
class _RSAPublicKey(object):
|
||||||
def __init__(self, backend, rsa_cdata):
|
def __init__(self, backend, rsa_cdata, evp_pkey):
|
||||||
self._backend = backend
|
self._backend = backend
|
||||||
self._rsa_cdata = rsa_cdata
|
self._rsa_cdata = rsa_cdata
|
||||||
|
|
||||||
evp_pkey = self._backend._lib.EVP_PKEY_new()
|
|
||||||
assert evp_pkey != self._backend._ffi.NULL
|
|
||||||
evp_pkey = self._backend._ffi.gc(
|
|
||||||
evp_pkey, self._backend._lib.EVP_PKEY_free
|
|
||||||
)
|
|
||||||
res = self._backend._lib.EVP_PKEY_set1_RSA(evp_pkey, rsa_cdata)
|
|
||||||
assert res == 1
|
|
||||||
self._evp_pkey = evp_pkey
|
self._evp_pkey = evp_pkey
|
||||||
|
|
||||||
self._key_size = self._backend._lib.BN_num_bits(self._rsa_cdata.n)
|
self._key_size = self._backend._lib.BN_num_bits(self._rsa_cdata.n)
|
||||||
|
|
||||||
@property
|
key_size = utils.read_only_property("_key_size")
|
||||||
def key_size(self):
|
|
||||||
return self._key_size
|
|
||||||
|
|
||||||
def verifier(self, signature, padding, algorithm):
|
def verifier(self, signature, padding, algorithm):
|
||||||
|
if not isinstance(signature, bytes):
|
||||||
|
raise TypeError("signature must be bytes.")
|
||||||
|
|
||||||
return _RSAVerificationContext(
|
return _RSAVerificationContext(
|
||||||
self._backend, self, signature, padding, algorithm
|
self._backend, self, signature, padding, algorithm
|
||||||
)
|
)
|
||||||
|
@ -601,3 +594,11 @@ class _RSAPublicKey(object):
|
||||||
e=self._backend._bn_to_int(self._rsa_cdata.e),
|
e=self._backend._bn_to_int(self._rsa_cdata.e),
|
||||||
n=self._backend._bn_to_int(self._rsa_cdata.n),
|
n=self._backend._bn_to_int(self._rsa_cdata.n),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def public_bytes(self, encoding, format):
|
||||||
|
return self._backend._public_key_bytes(
|
||||||
|
encoding,
|
||||||
|
format,
|
||||||
|
self._evp_pkey,
|
||||||
|
self._rsa_cdata
|
||||||
|
)
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
# This file is dual licensed under the terms of the Apache License, Version
|
||||||
|
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
|
||||||
|
# for complete details.
|
||||||
|
|
||||||
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
|
import six
|
||||||
|
|
||||||
|
|
||||||
|
def _truncate_digest(digest, order_bits):
|
||||||
|
digest_len = len(digest)
|
||||||
|
|
||||||
|
if 8 * digest_len > order_bits:
|
||||||
|
digest_len = (order_bits + 7) // 8
|
||||||
|
digest = digest[:digest_len]
|
||||||
|
|
||||||
|
if 8 * digest_len > order_bits:
|
||||||
|
rshift = 8 - (order_bits & 0x7)
|
||||||
|
assert 0 < rshift < 8
|
||||||
|
|
||||||
|
mask = 0xFF >> rshift << rshift
|
||||||
|
|
||||||
|
# Set the bottom rshift bits to 0
|
||||||
|
digest = digest[:-1] + six.int2byte(six.indexbytes(digest, -1) & mask)
|
||||||
|
|
||||||
|
return digest
|
|
@ -0,0 +1,940 @@
|
||||||
|
# This file is dual licensed under the terms of the Apache License, Version
|
||||||
|
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
|
||||||
|
# for complete details.
|
||||||
|
|
||||||
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
|
import datetime
|
||||||
|
import ipaddress
|
||||||
|
|
||||||
|
from email.utils import parseaddr
|
||||||
|
|
||||||
|
import idna
|
||||||
|
|
||||||
|
import six
|
||||||
|
|
||||||
|
from six.moves import urllib_parse
|
||||||
|
|
||||||
|
from cryptography import utils, x509
|
||||||
|
from cryptography.exceptions import UnsupportedAlgorithm
|
||||||
|
from cryptography.hazmat.primitives import hashes, serialization
|
||||||
|
from cryptography.x509.oid import (
|
||||||
|
CRLExtensionOID, CertificatePoliciesOID, ExtensionOID
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _obj2txt(backend, obj):
|
||||||
|
# Set to 80 on the recommendation of
|
||||||
|
# https://www.openssl.org/docs/crypto/OBJ_nid2ln.html#return_values
|
||||||
|
buf_len = 80
|
||||||
|
buf = backend._ffi.new("char[]", buf_len)
|
||||||
|
res = backend._lib.OBJ_obj2txt(buf, buf_len, obj, 1)
|
||||||
|
backend.openssl_assert(res > 0)
|
||||||
|
return backend._ffi.buffer(buf, res)[:].decode()
|
||||||
|
|
||||||
|
|
||||||
|
def _decode_x509_name_entry(backend, x509_name_entry):
|
||||||
|
obj = backend._lib.X509_NAME_ENTRY_get_object(x509_name_entry)
|
||||||
|
backend.openssl_assert(obj != backend._ffi.NULL)
|
||||||
|
data = backend._lib.X509_NAME_ENTRY_get_data(x509_name_entry)
|
||||||
|
backend.openssl_assert(data != backend._ffi.NULL)
|
||||||
|
value = backend._asn1_string_to_utf8(data)
|
||||||
|
oid = _obj2txt(backend, obj)
|
||||||
|
|
||||||
|
return x509.NameAttribute(x509.ObjectIdentifier(oid), value)
|
||||||
|
|
||||||
|
|
||||||
|
def _decode_x509_name(backend, x509_name):
|
||||||
|
count = backend._lib.X509_NAME_entry_count(x509_name)
|
||||||
|
attributes = []
|
||||||
|
for x in range(count):
|
||||||
|
entry = backend._lib.X509_NAME_get_entry(x509_name, x)
|
||||||
|
attributes.append(_decode_x509_name_entry(backend, entry))
|
||||||
|
|
||||||
|
return x509.Name(attributes)
|
||||||
|
|
||||||
|
|
||||||
|
def _decode_general_names(backend, gns):
|
||||||
|
num = backend._lib.sk_GENERAL_NAME_num(gns)
|
||||||
|
names = []
|
||||||
|
for i in range(num):
|
||||||
|
gn = backend._lib.sk_GENERAL_NAME_value(gns, i)
|
||||||
|
backend.openssl_assert(gn != backend._ffi.NULL)
|
||||||
|
names.append(_decode_general_name(backend, gn))
|
||||||
|
|
||||||
|
return names
|
||||||
|
|
||||||
|
|
||||||
|
def _decode_general_name(backend, gn):
|
||||||
|
if gn.type == backend._lib.GEN_DNS:
|
||||||
|
data = backend._asn1_string_to_bytes(gn.d.dNSName)
|
||||||
|
if not data:
|
||||||
|
decoded = u""
|
||||||
|
elif data.startswith(b"*."):
|
||||||
|
# This is a wildcard name. We need to remove the leading wildcard,
|
||||||
|
# IDNA decode, then re-add the wildcard. Wildcard characters should
|
||||||
|
# always be left-most (RFC 2595 section 2.4).
|
||||||
|
decoded = u"*." + idna.decode(data[2:])
|
||||||
|
else:
|
||||||
|
# Not a wildcard, decode away. If the string has a * in it anywhere
|
||||||
|
# invalid this will raise an InvalidCodePoint
|
||||||
|
decoded = idna.decode(data)
|
||||||
|
if data.startswith(b"."):
|
||||||
|
# idna strips leading periods. Name constraints can have that
|
||||||
|
# so we need to re-add it. Sigh.
|
||||||
|
decoded = u"." + decoded
|
||||||
|
|
||||||
|
return x509.DNSName(decoded)
|
||||||
|
elif gn.type == backend._lib.GEN_URI:
|
||||||
|
data = backend._asn1_string_to_ascii(gn.d.uniformResourceIdentifier)
|
||||||
|
parsed = urllib_parse.urlparse(data)
|
||||||
|
if parsed.hostname:
|
||||||
|
hostname = idna.decode(parsed.hostname)
|
||||||
|
else:
|
||||||
|
hostname = ""
|
||||||
|
if parsed.port:
|
||||||
|
netloc = hostname + u":" + six.text_type(parsed.port)
|
||||||
|
else:
|
||||||
|
netloc = hostname
|
||||||
|
|
||||||
|
# Note that building a URL in this fashion means it should be
|
||||||
|
# semantically indistinguishable from the original but is not
|
||||||
|
# guaranteed to be exactly the same.
|
||||||
|
uri = urllib_parse.urlunparse((
|
||||||
|
parsed.scheme,
|
||||||
|
netloc,
|
||||||
|
parsed.path,
|
||||||
|
parsed.params,
|
||||||
|
parsed.query,
|
||||||
|
parsed.fragment
|
||||||
|
))
|
||||||
|
return x509.UniformResourceIdentifier(uri)
|
||||||
|
elif gn.type == backend._lib.GEN_RID:
|
||||||
|
oid = _obj2txt(backend, gn.d.registeredID)
|
||||||
|
return x509.RegisteredID(x509.ObjectIdentifier(oid))
|
||||||
|
elif gn.type == backend._lib.GEN_IPADD:
|
||||||
|
data = backend._asn1_string_to_bytes(gn.d.iPAddress)
|
||||||
|
data_len = len(data)
|
||||||
|
if data_len == 8 or data_len == 32:
|
||||||
|
# This is an IPv4 or IPv6 Network and not a single IP. This
|
||||||
|
# type of data appears in Name Constraints. Unfortunately,
|
||||||
|
# ipaddress doesn't support packed bytes + netmask. Additionally,
|
||||||
|
# IPv6Network can only handle CIDR rather than the full 16 byte
|
||||||
|
# netmask. To handle this we convert the netmask to integer, then
|
||||||
|
# find the first 0 bit, which will be the prefix. If another 1
|
||||||
|
# bit is present after that the netmask is invalid.
|
||||||
|
base = ipaddress.ip_address(data[:data_len // 2])
|
||||||
|
netmask = ipaddress.ip_address(data[data_len // 2:])
|
||||||
|
bits = bin(int(netmask))[2:]
|
||||||
|
prefix = bits.find('0')
|
||||||
|
# If no 0 bits are found it is a /32 or /128
|
||||||
|
if prefix == -1:
|
||||||
|
prefix = len(bits)
|
||||||
|
|
||||||
|
if "1" in bits[prefix:]:
|
||||||
|
raise ValueError("Invalid netmask")
|
||||||
|
|
||||||
|
ip = ipaddress.ip_network(base.exploded + u"/{0}".format(prefix))
|
||||||
|
else:
|
||||||
|
ip = ipaddress.ip_address(data)
|
||||||
|
|
||||||
|
return x509.IPAddress(ip)
|
||||||
|
elif gn.type == backend._lib.GEN_DIRNAME:
|
||||||
|
return x509.DirectoryName(
|
||||||
|
_decode_x509_name(backend, gn.d.directoryName)
|
||||||
|
)
|
||||||
|
elif gn.type == backend._lib.GEN_EMAIL:
|
||||||
|
data = backend._asn1_string_to_ascii(gn.d.rfc822Name)
|
||||||
|
name, address = parseaddr(data)
|
||||||
|
parts = address.split(u"@")
|
||||||
|
if name or not address:
|
||||||
|
# parseaddr has found a name (e.g. Name <email>) or the entire
|
||||||
|
# value is an empty string.
|
||||||
|
raise ValueError("Invalid rfc822name value")
|
||||||
|
elif len(parts) == 1:
|
||||||
|
# Single label email name. This is valid for local delivery. No
|
||||||
|
# IDNA decoding can be done since there is no domain component.
|
||||||
|
return x509.RFC822Name(address)
|
||||||
|
else:
|
||||||
|
# A normal email of the form user@domain.com. Let's attempt to
|
||||||
|
# decode the domain component and return the entire address.
|
||||||
|
return x509.RFC822Name(
|
||||||
|
parts[0] + u"@" + idna.decode(parts[1])
|
||||||
|
)
|
||||||
|
elif gn.type == backend._lib.GEN_OTHERNAME:
|
||||||
|
type_id = _obj2txt(backend, gn.d.otherName.type_id)
|
||||||
|
value = backend._asn1_to_der(gn.d.otherName.value)
|
||||||
|
return x509.OtherName(x509.ObjectIdentifier(type_id), value)
|
||||||
|
else:
|
||||||
|
# x400Address or ediPartyName
|
||||||
|
raise x509.UnsupportedGeneralNameType(
|
||||||
|
"{0} is not a supported type".format(
|
||||||
|
x509._GENERAL_NAMES.get(gn.type, gn.type)
|
||||||
|
),
|
||||||
|
gn.type
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _decode_ocsp_no_check(backend, ext):
|
||||||
|
return x509.OCSPNoCheck()
|
||||||
|
|
||||||
|
|
||||||
|
class _X509ExtensionParser(object):
|
||||||
|
def __init__(self, ext_count, get_ext, handlers, unsupported_exts=None):
|
||||||
|
self.ext_count = ext_count
|
||||||
|
self.get_ext = get_ext
|
||||||
|
self.handlers = handlers
|
||||||
|
self.unsupported_exts = unsupported_exts
|
||||||
|
|
||||||
|
def parse(self, backend, x509_obj):
|
||||||
|
extensions = []
|
||||||
|
seen_oids = set()
|
||||||
|
for i in range(self.ext_count(backend, x509_obj)):
|
||||||
|
ext = self.get_ext(backend, x509_obj, i)
|
||||||
|
backend.openssl_assert(ext != backend._ffi.NULL)
|
||||||
|
crit = backend._lib.X509_EXTENSION_get_critical(ext)
|
||||||
|
critical = crit == 1
|
||||||
|
oid = x509.ObjectIdentifier(_obj2txt(backend, ext.object))
|
||||||
|
if oid in seen_oids:
|
||||||
|
raise x509.DuplicateExtension(
|
||||||
|
"Duplicate {0} extension found".format(oid), oid
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
handler = self.handlers[oid]
|
||||||
|
except KeyError:
|
||||||
|
if critical:
|
||||||
|
raise x509.UnsupportedExtension(
|
||||||
|
"Critical extension {0} is not currently supported"
|
||||||
|
.format(oid), oid
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# For extensions which are not supported by OpenSSL we pass the
|
||||||
|
# extension object directly to the parsing routine so it can
|
||||||
|
# be decoded manually.
|
||||||
|
if self.unsupported_exts and oid in self.unsupported_exts:
|
||||||
|
ext_data = ext
|
||||||
|
else:
|
||||||
|
ext_data = backend._lib.X509V3_EXT_d2i(ext)
|
||||||
|
if ext_data == backend._ffi.NULL:
|
||||||
|
backend._consume_errors()
|
||||||
|
raise ValueError(
|
||||||
|
"The {0} extension is invalid and can't be "
|
||||||
|
"parsed".format(oid)
|
||||||
|
)
|
||||||
|
|
||||||
|
value = handler(backend, ext_data)
|
||||||
|
extensions.append(x509.Extension(oid, critical, value))
|
||||||
|
|
||||||
|
seen_oids.add(oid)
|
||||||
|
|
||||||
|
return x509.Extensions(extensions)
|
||||||
|
|
||||||
|
|
||||||
|
@utils.register_interface(x509.Certificate)
|
||||||
|
class _Certificate(object):
|
||||||
|
def __init__(self, backend, x509):
|
||||||
|
self._backend = backend
|
||||||
|
self._x509 = x509
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "<Certificate(subject={0}, ...)>".format(self.subject)
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
if not isinstance(other, x509.Certificate):
|
||||||
|
return NotImplemented
|
||||||
|
|
||||||
|
res = self._backend._lib.X509_cmp(self._x509, other._x509)
|
||||||
|
return res == 0
|
||||||
|
|
||||||
|
def __ne__(self, other):
|
||||||
|
return not self == other
|
||||||
|
|
||||||
|
def __hash__(self):
|
||||||
|
return hash(self.public_bytes(serialization.Encoding.DER))
|
||||||
|
|
||||||
|
def fingerprint(self, algorithm):
|
||||||
|
h = hashes.Hash(algorithm, self._backend)
|
||||||
|
h.update(self.public_bytes(serialization.Encoding.DER))
|
||||||
|
return h.finalize()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def version(self):
|
||||||
|
version = self._backend._lib.X509_get_version(self._x509)
|
||||||
|
if version == 0:
|
||||||
|
return x509.Version.v1
|
||||||
|
elif version == 2:
|
||||||
|
return x509.Version.v3
|
||||||
|
else:
|
||||||
|
raise x509.InvalidVersion(
|
||||||
|
"{0} is not a valid X509 version".format(version), version
|
||||||
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def serial(self):
|
||||||
|
asn1_int = self._backend._lib.X509_get_serialNumber(self._x509)
|
||||||
|
self._backend.openssl_assert(asn1_int != self._backend._ffi.NULL)
|
||||||
|
return self._backend._asn1_integer_to_int(asn1_int)
|
||||||
|
|
||||||
|
def public_key(self):
|
||||||
|
pkey = self._backend._lib.X509_get_pubkey(self._x509)
|
||||||
|
if pkey == self._backend._ffi.NULL:
|
||||||
|
# Remove errors from the stack.
|
||||||
|
self._backend._consume_errors()
|
||||||
|
raise ValueError("Certificate public key is of an unknown type")
|
||||||
|
|
||||||
|
pkey = self._backend._ffi.gc(pkey, self._backend._lib.EVP_PKEY_free)
|
||||||
|
|
||||||
|
return self._backend._evp_pkey_to_public_key(pkey)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def not_valid_before(self):
|
||||||
|
asn1_time = self._backend._lib.X509_get_notBefore(self._x509)
|
||||||
|
return self._backend._parse_asn1_time(asn1_time)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def not_valid_after(self):
|
||||||
|
asn1_time = self._backend._lib.X509_get_notAfter(self._x509)
|
||||||
|
return self._backend._parse_asn1_time(asn1_time)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def issuer(self):
|
||||||
|
issuer = self._backend._lib.X509_get_issuer_name(self._x509)
|
||||||
|
self._backend.openssl_assert(issuer != self._backend._ffi.NULL)
|
||||||
|
return _decode_x509_name(self._backend, issuer)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def subject(self):
|
||||||
|
subject = self._backend._lib.X509_get_subject_name(self._x509)
|
||||||
|
self._backend.openssl_assert(subject != self._backend._ffi.NULL)
|
||||||
|
return _decode_x509_name(self._backend, subject)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def signature_hash_algorithm(self):
|
||||||
|
oid = _obj2txt(self._backend, self._x509.sig_alg.algorithm)
|
||||||
|
try:
|
||||||
|
return x509._SIG_OIDS_TO_HASH[oid]
|
||||||
|
except KeyError:
|
||||||
|
raise UnsupportedAlgorithm(
|
||||||
|
"Signature algorithm OID:{0} not recognized".format(oid)
|
||||||
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def extensions(self):
|
||||||
|
return _CERTIFICATE_EXTENSION_PARSER.parse(self._backend, self._x509)
|
||||||
|
|
||||||
|
def public_bytes(self, encoding):
|
||||||
|
bio = self._backend._create_mem_bio()
|
||||||
|
if encoding is serialization.Encoding.PEM:
|
||||||
|
res = self._backend._lib.PEM_write_bio_X509(bio, self._x509)
|
||||||
|
elif encoding is serialization.Encoding.DER:
|
||||||
|
res = self._backend._lib.i2d_X509_bio(bio, self._x509)
|
||||||
|
else:
|
||||||
|
raise TypeError("encoding must be an item from the Encoding enum")
|
||||||
|
|
||||||
|
self._backend.openssl_assert(res == 1)
|
||||||
|
return self._backend._read_mem_bio(bio)
|
||||||
|
|
||||||
|
|
||||||
|
def _decode_certificate_policies(backend, cp):
|
||||||
|
cp = backend._ffi.cast("Cryptography_STACK_OF_POLICYINFO *", cp)
|
||||||
|
cp = backend._ffi.gc(cp, backend._lib.sk_POLICYINFO_free)
|
||||||
|
num = backend._lib.sk_POLICYINFO_num(cp)
|
||||||
|
certificate_policies = []
|
||||||
|
for i in range(num):
|
||||||
|
qualifiers = None
|
||||||
|
pi = backend._lib.sk_POLICYINFO_value(cp, i)
|
||||||
|
oid = x509.ObjectIdentifier(_obj2txt(backend, pi.policyid))
|
||||||
|
if pi.qualifiers != backend._ffi.NULL:
|
||||||
|
qnum = backend._lib.sk_POLICYQUALINFO_num(pi.qualifiers)
|
||||||
|
qualifiers = []
|
||||||
|
for j in range(qnum):
|
||||||
|
pqi = backend._lib.sk_POLICYQUALINFO_value(
|
||||||
|
pi.qualifiers, j
|
||||||
|
)
|
||||||
|
pqualid = x509.ObjectIdentifier(
|
||||||
|
_obj2txt(backend, pqi.pqualid)
|
||||||
|
)
|
||||||
|
if pqualid == CertificatePoliciesOID.CPS_QUALIFIER:
|
||||||
|
cpsuri = backend._ffi.buffer(
|
||||||
|
pqi.d.cpsuri.data, pqi.d.cpsuri.length
|
||||||
|
)[:].decode('ascii')
|
||||||
|
qualifiers.append(cpsuri)
|
||||||
|
else:
|
||||||
|
assert pqualid == CertificatePoliciesOID.CPS_USER_NOTICE
|
||||||
|
user_notice = _decode_user_notice(
|
||||||
|
backend, pqi.d.usernotice
|
||||||
|
)
|
||||||
|
qualifiers.append(user_notice)
|
||||||
|
|
||||||
|
certificate_policies.append(
|
||||||
|
x509.PolicyInformation(oid, qualifiers)
|
||||||
|
)
|
||||||
|
|
||||||
|
return x509.CertificatePolicies(certificate_policies)
|
||||||
|
|
||||||
|
|
||||||
|
def _decode_user_notice(backend, un):
|
||||||
|
explicit_text = None
|
||||||
|
notice_reference = None
|
||||||
|
|
||||||
|
if un.exptext != backend._ffi.NULL:
|
||||||
|
explicit_text = backend._asn1_string_to_utf8(un.exptext)
|
||||||
|
|
||||||
|
if un.noticeref != backend._ffi.NULL:
|
||||||
|
organization = backend._asn1_string_to_utf8(un.noticeref.organization)
|
||||||
|
|
||||||
|
num = backend._lib.sk_ASN1_INTEGER_num(
|
||||||
|
un.noticeref.noticenos
|
||||||
|
)
|
||||||
|
notice_numbers = []
|
||||||
|
for i in range(num):
|
||||||
|
asn1_int = backend._lib.sk_ASN1_INTEGER_value(
|
||||||
|
un.noticeref.noticenos, i
|
||||||
|
)
|
||||||
|
notice_num = backend._asn1_integer_to_int(asn1_int)
|
||||||
|
notice_numbers.append(notice_num)
|
||||||
|
|
||||||
|
notice_reference = x509.NoticeReference(
|
||||||
|
organization, notice_numbers
|
||||||
|
)
|
||||||
|
|
||||||
|
return x509.UserNotice(notice_reference, explicit_text)
|
||||||
|
|
||||||
|
|
||||||
|
def _decode_basic_constraints(backend, bc_st):
|
||||||
|
basic_constraints = backend._ffi.cast("BASIC_CONSTRAINTS *", bc_st)
|
||||||
|
basic_constraints = backend._ffi.gc(
|
||||||
|
basic_constraints, backend._lib.BASIC_CONSTRAINTS_free
|
||||||
|
)
|
||||||
|
# The byte representation of an ASN.1 boolean true is \xff. OpenSSL
|
||||||
|
# chooses to just map this to its ordinal value, so true is 255 and
|
||||||
|
# false is 0.
|
||||||
|
ca = basic_constraints.ca == 255
|
||||||
|
if basic_constraints.pathlen == backend._ffi.NULL:
|
||||||
|
path_length = None
|
||||||
|
else:
|
||||||
|
path_length = backend._asn1_integer_to_int(basic_constraints.pathlen)
|
||||||
|
|
||||||
|
return x509.BasicConstraints(ca, path_length)
|
||||||
|
|
||||||
|
|
||||||
|
def _decode_subject_key_identifier(backend, asn1_string):
|
||||||
|
asn1_string = backend._ffi.cast("ASN1_OCTET_STRING *", asn1_string)
|
||||||
|
asn1_string = backend._ffi.gc(
|
||||||
|
asn1_string, backend._lib.ASN1_OCTET_STRING_free
|
||||||
|
)
|
||||||
|
return x509.SubjectKeyIdentifier(
|
||||||
|
backend._ffi.buffer(asn1_string.data, asn1_string.length)[:]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _decode_authority_key_identifier(backend, akid):
|
||||||
|
akid = backend._ffi.cast("AUTHORITY_KEYID *", akid)
|
||||||
|
akid = backend._ffi.gc(akid, backend._lib.AUTHORITY_KEYID_free)
|
||||||
|
key_identifier = None
|
||||||
|
authority_cert_issuer = None
|
||||||
|
authority_cert_serial_number = None
|
||||||
|
|
||||||
|
if akid.keyid != backend._ffi.NULL:
|
||||||
|
key_identifier = backend._ffi.buffer(
|
||||||
|
akid.keyid.data, akid.keyid.length
|
||||||
|
)[:]
|
||||||
|
|
||||||
|
if akid.issuer != backend._ffi.NULL:
|
||||||
|
authority_cert_issuer = _decode_general_names(
|
||||||
|
backend, akid.issuer
|
||||||
|
)
|
||||||
|
|
||||||
|
if akid.serial != backend._ffi.NULL:
|
||||||
|
authority_cert_serial_number = backend._asn1_integer_to_int(
|
||||||
|
akid.serial
|
||||||
|
)
|
||||||
|
|
||||||
|
return x509.AuthorityKeyIdentifier(
|
||||||
|
key_identifier, authority_cert_issuer, authority_cert_serial_number
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _decode_authority_information_access(backend, aia):
|
||||||
|
aia = backend._ffi.cast("Cryptography_STACK_OF_ACCESS_DESCRIPTION *", aia)
|
||||||
|
aia = backend._ffi.gc(aia, backend._lib.sk_ACCESS_DESCRIPTION_free)
|
||||||
|
num = backend._lib.sk_ACCESS_DESCRIPTION_num(aia)
|
||||||
|
access_descriptions = []
|
||||||
|
for i in range(num):
|
||||||
|
ad = backend._lib.sk_ACCESS_DESCRIPTION_value(aia, i)
|
||||||
|
backend.openssl_assert(ad.method != backend._ffi.NULL)
|
||||||
|
oid = x509.ObjectIdentifier(_obj2txt(backend, ad.method))
|
||||||
|
backend.openssl_assert(ad.location != backend._ffi.NULL)
|
||||||
|
gn = _decode_general_name(backend, ad.location)
|
||||||
|
access_descriptions.append(x509.AccessDescription(oid, gn))
|
||||||
|
|
||||||
|
return x509.AuthorityInformationAccess(access_descriptions)
|
||||||
|
|
||||||
|
|
||||||
|
def _decode_key_usage(backend, bit_string):
|
||||||
|
bit_string = backend._ffi.cast("ASN1_BIT_STRING *", bit_string)
|
||||||
|
bit_string = backend._ffi.gc(bit_string, backend._lib.ASN1_BIT_STRING_free)
|
||||||
|
get_bit = backend._lib.ASN1_BIT_STRING_get_bit
|
||||||
|
digital_signature = get_bit(bit_string, 0) == 1
|
||||||
|
content_commitment = get_bit(bit_string, 1) == 1
|
||||||
|
key_encipherment = get_bit(bit_string, 2) == 1
|
||||||
|
data_encipherment = get_bit(bit_string, 3) == 1
|
||||||
|
key_agreement = get_bit(bit_string, 4) == 1
|
||||||
|
key_cert_sign = get_bit(bit_string, 5) == 1
|
||||||
|
crl_sign = get_bit(bit_string, 6) == 1
|
||||||
|
encipher_only = get_bit(bit_string, 7) == 1
|
||||||
|
decipher_only = get_bit(bit_string, 8) == 1
|
||||||
|
return x509.KeyUsage(
|
||||||
|
digital_signature,
|
||||||
|
content_commitment,
|
||||||
|
key_encipherment,
|
||||||
|
data_encipherment,
|
||||||
|
key_agreement,
|
||||||
|
key_cert_sign,
|
||||||
|
crl_sign,
|
||||||
|
encipher_only,
|
||||||
|
decipher_only
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _decode_general_names_extension(backend, gns):
|
||||||
|
gns = backend._ffi.cast("GENERAL_NAMES *", gns)
|
||||||
|
gns = backend._ffi.gc(gns, backend._lib.GENERAL_NAMES_free)
|
||||||
|
general_names = _decode_general_names(backend, gns)
|
||||||
|
return general_names
|
||||||
|
|
||||||
|
|
||||||
|
def _decode_subject_alt_name(backend, ext):
|
||||||
|
return x509.SubjectAlternativeName(
|
||||||
|
_decode_general_names_extension(backend, ext)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _decode_issuer_alt_name(backend, ext):
|
||||||
|
return x509.IssuerAlternativeName(
|
||||||
|
_decode_general_names_extension(backend, ext)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _decode_name_constraints(backend, nc):
|
||||||
|
nc = backend._ffi.cast("NAME_CONSTRAINTS *", nc)
|
||||||
|
nc = backend._ffi.gc(nc, backend._lib.NAME_CONSTRAINTS_free)
|
||||||
|
permitted = _decode_general_subtrees(backend, nc.permittedSubtrees)
|
||||||
|
excluded = _decode_general_subtrees(backend, nc.excludedSubtrees)
|
||||||
|
return x509.NameConstraints(
|
||||||
|
permitted_subtrees=permitted, excluded_subtrees=excluded
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _decode_general_subtrees(backend, stack_subtrees):
|
||||||
|
if stack_subtrees == backend._ffi.NULL:
|
||||||
|
return None
|
||||||
|
|
||||||
|
num = backend._lib.sk_GENERAL_SUBTREE_num(stack_subtrees)
|
||||||
|
subtrees = []
|
||||||
|
|
||||||
|
for i in range(num):
|
||||||
|
obj = backend._lib.sk_GENERAL_SUBTREE_value(stack_subtrees, i)
|
||||||
|
backend.openssl_assert(obj != backend._ffi.NULL)
|
||||||
|
name = _decode_general_name(backend, obj.base)
|
||||||
|
subtrees.append(name)
|
||||||
|
|
||||||
|
return subtrees
|
||||||
|
|
||||||
|
|
||||||
|
def _decode_extended_key_usage(backend, sk):
|
||||||
|
sk = backend._ffi.cast("Cryptography_STACK_OF_ASN1_OBJECT *", sk)
|
||||||
|
sk = backend._ffi.gc(sk, backend._lib.sk_ASN1_OBJECT_free)
|
||||||
|
num = backend._lib.sk_ASN1_OBJECT_num(sk)
|
||||||
|
ekus = []
|
||||||
|
|
||||||
|
for i in range(num):
|
||||||
|
obj = backend._lib.sk_ASN1_OBJECT_value(sk, i)
|
||||||
|
backend.openssl_assert(obj != backend._ffi.NULL)
|
||||||
|
oid = x509.ObjectIdentifier(_obj2txt(backend, obj))
|
||||||
|
ekus.append(oid)
|
||||||
|
|
||||||
|
return x509.ExtendedKeyUsage(ekus)
|
||||||
|
|
||||||
|
|
||||||
|
_DISTPOINT_TYPE_FULLNAME = 0
|
||||||
|
_DISTPOINT_TYPE_RELATIVENAME = 1
|
||||||
|
|
||||||
|
|
||||||
|
def _decode_crl_distribution_points(backend, cdps):
|
||||||
|
cdps = backend._ffi.cast("Cryptography_STACK_OF_DIST_POINT *", cdps)
|
||||||
|
cdps = backend._ffi.gc(cdps, backend._lib.sk_DIST_POINT_free)
|
||||||
|
num = backend._lib.sk_DIST_POINT_num(cdps)
|
||||||
|
|
||||||
|
dist_points = []
|
||||||
|
for i in range(num):
|
||||||
|
full_name = None
|
||||||
|
relative_name = None
|
||||||
|
crl_issuer = None
|
||||||
|
reasons = None
|
||||||
|
cdp = backend._lib.sk_DIST_POINT_value(cdps, i)
|
||||||
|
if cdp.reasons != backend._ffi.NULL:
|
||||||
|
# We will check each bit from RFC 5280
|
||||||
|
# ReasonFlags ::= BIT STRING {
|
||||||
|
# unused (0),
|
||||||
|
# keyCompromise (1),
|
||||||
|
# cACompromise (2),
|
||||||
|
# affiliationChanged (3),
|
||||||
|
# superseded (4),
|
||||||
|
# cessationOfOperation (5),
|
||||||
|
# certificateHold (6),
|
||||||
|
# privilegeWithdrawn (7),
|
||||||
|
# aACompromise (8) }
|
||||||
|
reasons = []
|
||||||
|
get_bit = backend._lib.ASN1_BIT_STRING_get_bit
|
||||||
|
if get_bit(cdp.reasons, 1):
|
||||||
|
reasons.append(x509.ReasonFlags.key_compromise)
|
||||||
|
|
||||||
|
if get_bit(cdp.reasons, 2):
|
||||||
|
reasons.append(x509.ReasonFlags.ca_compromise)
|
||||||
|
|
||||||
|
if get_bit(cdp.reasons, 3):
|
||||||
|
reasons.append(x509.ReasonFlags.affiliation_changed)
|
||||||
|
|
||||||
|
if get_bit(cdp.reasons, 4):
|
||||||
|
reasons.append(x509.ReasonFlags.superseded)
|
||||||
|
|
||||||
|
if get_bit(cdp.reasons, 5):
|
||||||
|
reasons.append(x509.ReasonFlags.cessation_of_operation)
|
||||||
|
|
||||||
|
if get_bit(cdp.reasons, 6):
|
||||||
|
reasons.append(x509.ReasonFlags.certificate_hold)
|
||||||
|
|
||||||
|
if get_bit(cdp.reasons, 7):
|
||||||
|
reasons.append(x509.ReasonFlags.privilege_withdrawn)
|
||||||
|
|
||||||
|
if get_bit(cdp.reasons, 8):
|
||||||
|
reasons.append(x509.ReasonFlags.aa_compromise)
|
||||||
|
|
||||||
|
reasons = frozenset(reasons)
|
||||||
|
|
||||||
|
if cdp.CRLissuer != backend._ffi.NULL:
|
||||||
|
crl_issuer = _decode_general_names(backend, cdp.CRLissuer)
|
||||||
|
|
||||||
|
# Certificates may have a crl_issuer/reasons and no distribution
|
||||||
|
# point so make sure it's not null.
|
||||||
|
if cdp.distpoint != backend._ffi.NULL:
|
||||||
|
# Type 0 is fullName, there is no #define for it in the code.
|
||||||
|
if cdp.distpoint.type == _DISTPOINT_TYPE_FULLNAME:
|
||||||
|
full_name = _decode_general_names(
|
||||||
|
backend, cdp.distpoint.name.fullname
|
||||||
|
)
|
||||||
|
# OpenSSL code doesn't test for a specific type for
|
||||||
|
# relativename, everything that isn't fullname is considered
|
||||||
|
# relativename.
|
||||||
|
else:
|
||||||
|
rns = cdp.distpoint.name.relativename
|
||||||
|
rnum = backend._lib.sk_X509_NAME_ENTRY_num(rns)
|
||||||
|
attributes = []
|
||||||
|
for i in range(rnum):
|
||||||
|
rn = backend._lib.sk_X509_NAME_ENTRY_value(
|
||||||
|
rns, i
|
||||||
|
)
|
||||||
|
backend.openssl_assert(rn != backend._ffi.NULL)
|
||||||
|
attributes.append(
|
||||||
|
_decode_x509_name_entry(backend, rn)
|
||||||
|
)
|
||||||
|
|
||||||
|
relative_name = x509.Name(attributes)
|
||||||
|
|
||||||
|
dist_points.append(
|
||||||
|
x509.DistributionPoint(
|
||||||
|
full_name, relative_name, reasons, crl_issuer
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
return x509.CRLDistributionPoints(dist_points)
|
||||||
|
|
||||||
|
|
||||||
|
def _decode_inhibit_any_policy(backend, asn1_int):
|
||||||
|
asn1_int = backend._ffi.cast("ASN1_INTEGER *", asn1_int)
|
||||||
|
asn1_int = backend._ffi.gc(asn1_int, backend._lib.ASN1_INTEGER_free)
|
||||||
|
skip_certs = backend._asn1_integer_to_int(asn1_int)
|
||||||
|
return x509.InhibitAnyPolicy(skip_certs)
|
||||||
|
|
||||||
|
|
||||||
|
_CRL_REASON_CODE_TO_ENUM = {
|
||||||
|
0: x509.ReasonFlags.unspecified,
|
||||||
|
1: x509.ReasonFlags.key_compromise,
|
||||||
|
2: x509.ReasonFlags.ca_compromise,
|
||||||
|
3: x509.ReasonFlags.affiliation_changed,
|
||||||
|
4: x509.ReasonFlags.superseded,
|
||||||
|
5: x509.ReasonFlags.cessation_of_operation,
|
||||||
|
6: x509.ReasonFlags.certificate_hold,
|
||||||
|
8: x509.ReasonFlags.remove_from_crl,
|
||||||
|
9: x509.ReasonFlags.privilege_withdrawn,
|
||||||
|
10: x509.ReasonFlags.aa_compromise,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _decode_crl_reason(backend, enum):
|
||||||
|
enum = backend._ffi.cast("ASN1_ENUMERATED *", enum)
|
||||||
|
enum = backend._ffi.gc(enum, backend._lib.ASN1_ENUMERATED_free)
|
||||||
|
code = backend._lib.ASN1_ENUMERATED_get(enum)
|
||||||
|
|
||||||
|
try:
|
||||||
|
return _CRL_REASON_CODE_TO_ENUM[code]
|
||||||
|
except KeyError:
|
||||||
|
raise ValueError("Unsupported reason code: {0}".format(code))
|
||||||
|
|
||||||
|
|
||||||
|
def _decode_invalidity_date(backend, inv_date):
|
||||||
|
generalized_time = backend._ffi.cast(
|
||||||
|
"ASN1_GENERALIZEDTIME *", inv_date
|
||||||
|
)
|
||||||
|
generalized_time = backend._ffi.gc(
|
||||||
|
generalized_time, backend._lib.ASN1_GENERALIZEDTIME_free
|
||||||
|
)
|
||||||
|
time = backend._ffi.string(
|
||||||
|
backend._lib.ASN1_STRING_data(
|
||||||
|
backend._ffi.cast("ASN1_STRING *", generalized_time)
|
||||||
|
)
|
||||||
|
).decode("ascii")
|
||||||
|
return datetime.datetime.strptime(time, "%Y%m%d%H%M%SZ")
|
||||||
|
|
||||||
|
|
||||||
|
def _decode_cert_issuer(backend, ext):
|
||||||
|
"""
|
||||||
|
This handler decodes the CertificateIssuer entry extension directly
|
||||||
|
from the X509_EXTENSION object. This is necessary because this entry
|
||||||
|
extension is not directly supported by OpenSSL 0.9.8.
|
||||||
|
"""
|
||||||
|
|
||||||
|
data_ptr_ptr = backend._ffi.new("const unsigned char **")
|
||||||
|
data_ptr_ptr[0] = ext.value.data
|
||||||
|
gns = backend._lib.d2i_GENERAL_NAMES(
|
||||||
|
backend._ffi.NULL, data_ptr_ptr, ext.value.length
|
||||||
|
)
|
||||||
|
|
||||||
|
# Check the result of d2i_GENERAL_NAMES() is valid. Usually this is covered
|
||||||
|
# in _X509ExtensionParser but since we are responsible for decoding this
|
||||||
|
# entry extension ourselves, we have to this here.
|
||||||
|
if gns == backend._ffi.NULL:
|
||||||
|
backend._consume_errors()
|
||||||
|
raise ValueError(
|
||||||
|
"The {0} extension is corrupted and can't be parsed".format(
|
||||||
|
CRLExtensionOID.CERTIFICATE_ISSUER))
|
||||||
|
|
||||||
|
gns = backend._ffi.gc(gns, backend._lib.GENERAL_NAMES_free)
|
||||||
|
return x509.GeneralNames(_decode_general_names(backend, gns))
|
||||||
|
|
||||||
|
|
||||||
|
@utils.register_interface(x509.RevokedCertificate)
|
||||||
|
class _RevokedCertificate(object):
|
||||||
|
def __init__(self, backend, x509_revoked):
|
||||||
|
self._backend = backend
|
||||||
|
self._x509_revoked = x509_revoked
|
||||||
|
|
||||||
|
@property
|
||||||
|
def serial_number(self):
|
||||||
|
asn1_int = self._x509_revoked.serialNumber
|
||||||
|
self._backend.openssl_assert(asn1_int != self._backend._ffi.NULL)
|
||||||
|
return self._backend._asn1_integer_to_int(asn1_int)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def revocation_date(self):
|
||||||
|
return self._backend._parse_asn1_time(
|
||||||
|
self._x509_revoked.revocationDate)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def extensions(self):
|
||||||
|
return _REVOKED_CERTIFICATE_EXTENSION_PARSER.parse(
|
||||||
|
self._backend, self._x509_revoked
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@utils.register_interface(x509.CertificateRevocationList)
|
||||||
|
class _CertificateRevocationList(object):
|
||||||
|
def __init__(self, backend, x509_crl):
|
||||||
|
self._backend = backend
|
||||||
|
self._x509_crl = x509_crl
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
if not isinstance(other, x509.CertificateRevocationList):
|
||||||
|
return NotImplemented
|
||||||
|
|
||||||
|
res = self._backend._lib.X509_CRL_cmp(self._x509_crl, other._x509_crl)
|
||||||
|
return res == 0
|
||||||
|
|
||||||
|
def __ne__(self, other):
|
||||||
|
return not self == other
|
||||||
|
|
||||||
|
def fingerprint(self, algorithm):
|
||||||
|
h = hashes.Hash(algorithm, self._backend)
|
||||||
|
bio = self._backend._create_mem_bio()
|
||||||
|
res = self._backend._lib.i2d_X509_CRL_bio(
|
||||||
|
bio, self._x509_crl
|
||||||
|
)
|
||||||
|
self._backend.openssl_assert(res == 1)
|
||||||
|
der = self._backend._read_mem_bio(bio)
|
||||||
|
h.update(der)
|
||||||
|
return h.finalize()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def signature_hash_algorithm(self):
|
||||||
|
oid = _obj2txt(self._backend, self._x509_crl.sig_alg.algorithm)
|
||||||
|
try:
|
||||||
|
return x509._SIG_OIDS_TO_HASH[oid]
|
||||||
|
except KeyError:
|
||||||
|
raise UnsupportedAlgorithm(
|
||||||
|
"Signature algorithm OID:{0} not recognized".format(oid)
|
||||||
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def issuer(self):
|
||||||
|
issuer = self._backend._lib.X509_CRL_get_issuer(self._x509_crl)
|
||||||
|
self._backend.openssl_assert(issuer != self._backend._ffi.NULL)
|
||||||
|
return _decode_x509_name(self._backend, issuer)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def next_update(self):
|
||||||
|
nu = self._backend._lib.X509_CRL_get_nextUpdate(self._x509_crl)
|
||||||
|
self._backend.openssl_assert(nu != self._backend._ffi.NULL)
|
||||||
|
return self._backend._parse_asn1_time(nu)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def last_update(self):
|
||||||
|
lu = self._backend._lib.X509_CRL_get_lastUpdate(self._x509_crl)
|
||||||
|
self._backend.openssl_assert(lu != self._backend._ffi.NULL)
|
||||||
|
return self._backend._parse_asn1_time(lu)
|
||||||
|
|
||||||
|
def _revoked_certificates(self):
|
||||||
|
revoked = self._backend._lib.X509_CRL_get_REVOKED(self._x509_crl)
|
||||||
|
self._backend.openssl_assert(revoked != self._backend._ffi.NULL)
|
||||||
|
|
||||||
|
num = self._backend._lib.sk_X509_REVOKED_num(revoked)
|
||||||
|
revoked_list = []
|
||||||
|
for i in range(num):
|
||||||
|
r = self._backend._lib.sk_X509_REVOKED_value(revoked, i)
|
||||||
|
self._backend.openssl_assert(r != self._backend._ffi.NULL)
|
||||||
|
revoked_list.append(_RevokedCertificate(self._backend, r))
|
||||||
|
|
||||||
|
return revoked_list
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
return iter(self._revoked_certificates())
|
||||||
|
|
||||||
|
def __getitem__(self, idx):
|
||||||
|
return self._revoked_certificates()[idx]
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return len(self._revoked_certificates())
|
||||||
|
|
||||||
|
@property
|
||||||
|
def extensions(self):
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
|
||||||
|
@utils.register_interface(x509.CertificateSigningRequest)
|
||||||
|
class _CertificateSigningRequest(object):
|
||||||
|
def __init__(self, backend, x509_req):
|
||||||
|
self._backend = backend
|
||||||
|
self._x509_req = x509_req
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
if not isinstance(other, _CertificateSigningRequest):
|
||||||
|
return NotImplemented
|
||||||
|
|
||||||
|
self_bytes = self.public_bytes(serialization.Encoding.DER)
|
||||||
|
other_bytes = other.public_bytes(serialization.Encoding.DER)
|
||||||
|
return self_bytes == other_bytes
|
||||||
|
|
||||||
|
def __ne__(self, other):
|
||||||
|
return not self == other
|
||||||
|
|
||||||
|
def __hash__(self):
|
||||||
|
return hash(self.public_bytes(serialization.Encoding.DER))
|
||||||
|
|
||||||
|
def public_key(self):
|
||||||
|
pkey = self._backend._lib.X509_REQ_get_pubkey(self._x509_req)
|
||||||
|
self._backend.openssl_assert(pkey != self._backend._ffi.NULL)
|
||||||
|
pkey = self._backend._ffi.gc(pkey, self._backend._lib.EVP_PKEY_free)
|
||||||
|
return self._backend._evp_pkey_to_public_key(pkey)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def subject(self):
|
||||||
|
subject = self._backend._lib.X509_REQ_get_subject_name(self._x509_req)
|
||||||
|
self._backend.openssl_assert(subject != self._backend._ffi.NULL)
|
||||||
|
return _decode_x509_name(self._backend, subject)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def signature_hash_algorithm(self):
|
||||||
|
oid = _obj2txt(self._backend, self._x509_req.sig_alg.algorithm)
|
||||||
|
try:
|
||||||
|
return x509._SIG_OIDS_TO_HASH[oid]
|
||||||
|
except KeyError:
|
||||||
|
raise UnsupportedAlgorithm(
|
||||||
|
"Signature algorithm OID:{0} not recognized".format(oid)
|
||||||
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def extensions(self):
|
||||||
|
x509_exts = self._backend._lib.X509_REQ_get_extensions(self._x509_req)
|
||||||
|
return _CSR_EXTENSION_PARSER.parse(self._backend, x509_exts)
|
||||||
|
|
||||||
|
def public_bytes(self, encoding):
|
||||||
|
bio = self._backend._create_mem_bio()
|
||||||
|
if encoding is serialization.Encoding.PEM:
|
||||||
|
res = self._backend._lib.PEM_write_bio_X509_REQ(
|
||||||
|
bio, self._x509_req
|
||||||
|
)
|
||||||
|
elif encoding is serialization.Encoding.DER:
|
||||||
|
res = self._backend._lib.i2d_X509_REQ_bio(bio, self._x509_req)
|
||||||
|
else:
|
||||||
|
raise TypeError("encoding must be an item from the Encoding enum")
|
||||||
|
|
||||||
|
self._backend.openssl_assert(res == 1)
|
||||||
|
return self._backend._read_mem_bio(bio)
|
||||||
|
|
||||||
|
|
||||||
|
_EXTENSION_HANDLERS = {
|
||||||
|
ExtensionOID.BASIC_CONSTRAINTS: _decode_basic_constraints,
|
||||||
|
ExtensionOID.SUBJECT_KEY_IDENTIFIER: _decode_subject_key_identifier,
|
||||||
|
ExtensionOID.KEY_USAGE: _decode_key_usage,
|
||||||
|
ExtensionOID.SUBJECT_ALTERNATIVE_NAME: _decode_subject_alt_name,
|
||||||
|
ExtensionOID.EXTENDED_KEY_USAGE: _decode_extended_key_usage,
|
||||||
|
ExtensionOID.AUTHORITY_KEY_IDENTIFIER: _decode_authority_key_identifier,
|
||||||
|
ExtensionOID.AUTHORITY_INFORMATION_ACCESS: (
|
||||||
|
_decode_authority_information_access
|
||||||
|
),
|
||||||
|
ExtensionOID.CERTIFICATE_POLICIES: _decode_certificate_policies,
|
||||||
|
ExtensionOID.CRL_DISTRIBUTION_POINTS: _decode_crl_distribution_points,
|
||||||
|
ExtensionOID.OCSP_NO_CHECK: _decode_ocsp_no_check,
|
||||||
|
ExtensionOID.INHIBIT_ANY_POLICY: _decode_inhibit_any_policy,
|
||||||
|
ExtensionOID.ISSUER_ALTERNATIVE_NAME: _decode_issuer_alt_name,
|
||||||
|
ExtensionOID.NAME_CONSTRAINTS: _decode_name_constraints,
|
||||||
|
}
|
||||||
|
|
||||||
|
_REVOKED_EXTENSION_HANDLERS = {
|
||||||
|
CRLExtensionOID.CRL_REASON: _decode_crl_reason,
|
||||||
|
CRLExtensionOID.INVALIDITY_DATE: _decode_invalidity_date,
|
||||||
|
CRLExtensionOID.CERTIFICATE_ISSUER: _decode_cert_issuer,
|
||||||
|
}
|
||||||
|
|
||||||
|
_REVOKED_UNSUPPORTED_EXTENSIONS = set([
|
||||||
|
CRLExtensionOID.CERTIFICATE_ISSUER,
|
||||||
|
])
|
||||||
|
|
||||||
|
_CERTIFICATE_EXTENSION_PARSER = _X509ExtensionParser(
|
||||||
|
ext_count=lambda backend, x: backend._lib.X509_get_ext_count(x),
|
||||||
|
get_ext=lambda backend, x, i: backend._lib.X509_get_ext(x, i),
|
||||||
|
handlers=_EXTENSION_HANDLERS
|
||||||
|
)
|
||||||
|
|
||||||
|
_CSR_EXTENSION_PARSER = _X509ExtensionParser(
|
||||||
|
ext_count=lambda backend, x: backend._lib.sk_X509_EXTENSION_num(x),
|
||||||
|
get_ext=lambda backend, x, i: backend._lib.sk_X509_EXTENSION_value(x, i),
|
||||||
|
handlers=_EXTENSION_HANDLERS
|
||||||
|
)
|
||||||
|
|
||||||
|
_REVOKED_CERTIFICATE_EXTENSION_PARSER = _X509ExtensionParser(
|
||||||
|
ext_count=lambda backend, x: backend._lib.X509_REVOKED_get_ext_count(x),
|
||||||
|
get_ext=lambda backend, x, i: backend._lib.X509_REVOKED_get_ext(x, i),
|
||||||
|
handlers=_REVOKED_EXTENSION_HANDLERS,
|
||||||
|
unsupported_exts=_REVOKED_UNSUPPORTED_EXTENSIONS
|
||||||
|
)
|
|
@ -1,14 +1,5 @@
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# This file is dual licensed under the terms of the Apache License, Version
|
||||||
# you may not use this file except in compliance with the License.
|
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
|
||||||
# You may obtain a copy of the License at
|
# for complete details.
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
# implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,14 +1,5 @@
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# This file is dual licensed under the terms of the Apache License, Version
|
||||||
# you may not use this file except in compliance with the License.
|
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
|
||||||
# You may obtain a copy of the License at
|
# for complete details.
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
# implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
|
@ -1,54 +1,15 @@
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# This file is dual licensed under the terms of the Apache License, Version
|
||||||
# you may not use this file except in compliance with the License.
|
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
|
||||||
# You may obtain a copy of the License at
|
# for complete details.
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
# implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
from cryptography.hazmat.bindings.utils import build_ffi
|
from cryptography.hazmat.bindings._commoncrypto import ffi, lib
|
||||||
|
|
||||||
|
|
||||||
class Binding(object):
|
class Binding(object):
|
||||||
"""
|
"""
|
||||||
CommonCrypto API wrapper.
|
CommonCrypto API wrapper.
|
||||||
"""
|
"""
|
||||||
_module_prefix = "cryptography.hazmat.bindings.commoncrypto."
|
lib = lib
|
||||||
_modules = [
|
ffi = ffi
|
||||||
"cf",
|
|
||||||
"common_digest",
|
|
||||||
"common_hmac",
|
|
||||||
"common_key_derivation",
|
|
||||||
"common_cryptor",
|
|
||||||
"secimport",
|
|
||||||
"secitem",
|
|
||||||
"seckey",
|
|
||||||
"seckeychain",
|
|
||||||
"sectransform",
|
|
||||||
]
|
|
||||||
|
|
||||||
ffi = None
|
|
||||||
lib = None
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self._ensure_ffi_initialized()
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def _ensure_ffi_initialized(cls):
|
|
||||||
if cls.ffi is not None and cls.lib is not None:
|
|
||||||
return
|
|
||||||
|
|
||||||
cls.ffi, cls.lib = build_ffi(
|
|
||||||
module_prefix=cls._module_prefix,
|
|
||||||
modules=cls._modules,
|
|
||||||
extra_link_args=[
|
|
||||||
"-framework", "Security", "-framework", "CoreFoundation"
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
|
@ -1,114 +0,0 @@
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
# you may not use this file except in compliance with the License.
|
|
||||||
# You may obtain a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
# implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
|
||||||
|
|
||||||
INCLUDES = """
|
|
||||||
#include <CoreFoundation/CoreFoundation.h>
|
|
||||||
"""
|
|
||||||
|
|
||||||
TYPES = """
|
|
||||||
typedef bool Boolean;
|
|
||||||
typedef signed long OSStatus;
|
|
||||||
typedef unsigned char UInt8;
|
|
||||||
typedef uint32_t UInt32;
|
|
||||||
|
|
||||||
typedef const void * CFAllocatorRef;
|
|
||||||
const CFAllocatorRef kCFAllocatorDefault;
|
|
||||||
typedef const void * CFDataRef;
|
|
||||||
typedef signed long long CFIndex;
|
|
||||||
typedef ... *CFStringRef;
|
|
||||||
typedef ... *CFArrayRef;
|
|
||||||
typedef ... *CFBooleanRef;
|
|
||||||
typedef ... *CFErrorRef;
|
|
||||||
typedef ... *CFNumberRef;
|
|
||||||
typedef ... *CFTypeRef;
|
|
||||||
typedef ... *CFDictionaryRef;
|
|
||||||
typedef ... *CFMutableDictionaryRef;
|
|
||||||
typedef struct {
|
|
||||||
...;
|
|
||||||
} CFDictionaryKeyCallBacks;
|
|
||||||
typedef struct {
|
|
||||||
...;
|
|
||||||
} CFDictionaryValueCallBacks;
|
|
||||||
typedef struct {
|
|
||||||
...;
|
|
||||||
} CFRange;
|
|
||||||
|
|
||||||
typedef UInt32 CFStringEncoding;
|
|
||||||
enum {
|
|
||||||
kCFStringEncodingASCII = 0x0600
|
|
||||||
};
|
|
||||||
|
|
||||||
enum {
|
|
||||||
kCFNumberSInt8Type = 1,
|
|
||||||
kCFNumberSInt16Type = 2,
|
|
||||||
kCFNumberSInt32Type = 3,
|
|
||||||
kCFNumberSInt64Type = 4,
|
|
||||||
kCFNumberFloat32Type = 5,
|
|
||||||
kCFNumberFloat64Type = 6,
|
|
||||||
kCFNumberCharType = 7,
|
|
||||||
kCFNumberShortType = 8,
|
|
||||||
kCFNumberIntType = 9,
|
|
||||||
kCFNumberLongType = 10,
|
|
||||||
kCFNumberLongLongType = 11,
|
|
||||||
kCFNumberFloatType = 12,
|
|
||||||
kCFNumberDoubleType = 13,
|
|
||||||
kCFNumberCFIndexType = 14,
|
|
||||||
kCFNumberNSIntegerType = 15,
|
|
||||||
kCFNumberCGFloatType = 16,
|
|
||||||
kCFNumberMaxType = 16
|
|
||||||
};
|
|
||||||
typedef int CFNumberType;
|
|
||||||
|
|
||||||
const CFDictionaryKeyCallBacks kCFTypeDictionaryKeyCallBacks;
|
|
||||||
const CFDictionaryValueCallBacks kCFTypeDictionaryValueCallBacks;
|
|
||||||
|
|
||||||
const CFBooleanRef kCFBooleanTrue;
|
|
||||||
const CFBooleanRef kCFBooleanFalse;
|
|
||||||
"""
|
|
||||||
|
|
||||||
FUNCTIONS = """
|
|
||||||
CFDataRef CFDataCreate(CFAllocatorRef, const UInt8 *, CFIndex);
|
|
||||||
CFStringRef CFStringCreateWithCString(CFAllocatorRef, const char *,
|
|
||||||
CFStringEncoding);
|
|
||||||
CFDictionaryRef CFDictionaryCreate(CFAllocatorRef, const void **,
|
|
||||||
const void **, CFIndex,
|
|
||||||
const CFDictionaryKeyCallBacks *,
|
|
||||||
const CFDictionaryValueCallBacks *);
|
|
||||||
CFMutableDictionaryRef CFDictionaryCreateMutable(
|
|
||||||
CFAllocatorRef,
|
|
||||||
CFIndex,
|
|
||||||
const CFDictionaryKeyCallBacks *,
|
|
||||||
const CFDictionaryValueCallBacks *
|
|
||||||
);
|
|
||||||
void CFDictionarySetValue(CFMutableDictionaryRef, const void *, const void *);
|
|
||||||
CFIndex CFArrayGetCount(CFArrayRef);
|
|
||||||
const void *CFArrayGetValueAtIndex(CFArrayRef, CFIndex);
|
|
||||||
CFIndex CFDataGetLength(CFDataRef);
|
|
||||||
void CFDataGetBytes(CFDataRef, CFRange, UInt8 *);
|
|
||||||
CFRange CFRangeMake(CFIndex, CFIndex);
|
|
||||||
void CFShow(CFTypeRef);
|
|
||||||
Boolean CFBooleanGetValue(CFBooleanRef);
|
|
||||||
CFNumberRef CFNumberCreate(CFAllocatorRef, CFNumberType, const void *);
|
|
||||||
void CFRelease(CFTypeRef);
|
|
||||||
CFTypeRef CFRetain(CFTypeRef);
|
|
||||||
"""
|
|
||||||
|
|
||||||
MACROS = """
|
|
||||||
"""
|
|
||||||
|
|
||||||
CUSTOMIZATIONS = """
|
|
||||||
"""
|
|
||||||
|
|
||||||
CONDITIONAL_NAMES = {}
|
|
|
@ -1,110 +0,0 @@
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
# you may not use this file except in compliance with the License.
|
|
||||||
# You may obtain a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
# implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
|
||||||
|
|
||||||
INCLUDES = """
|
|
||||||
#include <CommonCrypto/CommonCryptor.h>
|
|
||||||
"""
|
|
||||||
|
|
||||||
TYPES = """
|
|
||||||
enum {
|
|
||||||
kCCAlgorithmAES128 = 0,
|
|
||||||
kCCAlgorithmDES,
|
|
||||||
kCCAlgorithm3DES,
|
|
||||||
kCCAlgorithmCAST,
|
|
||||||
kCCAlgorithmRC4,
|
|
||||||
kCCAlgorithmRC2,
|
|
||||||
kCCAlgorithmBlowfish
|
|
||||||
};
|
|
||||||
typedef uint32_t CCAlgorithm;
|
|
||||||
enum {
|
|
||||||
kCCSuccess = 0,
|
|
||||||
kCCParamError = -4300,
|
|
||||||
kCCBufferTooSmall = -4301,
|
|
||||||
kCCMemoryFailure = -4302,
|
|
||||||
kCCAlignmentError = -4303,
|
|
||||||
kCCDecodeError = -4304,
|
|
||||||
kCCUnimplemented = -4305
|
|
||||||
};
|
|
||||||
typedef int32_t CCCryptorStatus;
|
|
||||||
typedef uint32_t CCOptions;
|
|
||||||
enum {
|
|
||||||
kCCEncrypt = 0,
|
|
||||||
kCCDecrypt,
|
|
||||||
};
|
|
||||||
typedef uint32_t CCOperation;
|
|
||||||
typedef ... *CCCryptorRef;
|
|
||||||
|
|
||||||
enum {
|
|
||||||
kCCModeOptionCTR_LE = 0x0001,
|
|
||||||
kCCModeOptionCTR_BE = 0x0002
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef uint32_t CCModeOptions;
|
|
||||||
|
|
||||||
enum {
|
|
||||||
kCCModeECB = 1,
|
|
||||||
kCCModeCBC = 2,
|
|
||||||
kCCModeCFB = 3,
|
|
||||||
kCCModeCTR = 4,
|
|
||||||
kCCModeF8 = 5,
|
|
||||||
kCCModeLRW = 6,
|
|
||||||
kCCModeOFB = 7,
|
|
||||||
kCCModeXTS = 8,
|
|
||||||
kCCModeRC4 = 9,
|
|
||||||
kCCModeCFB8 = 10,
|
|
||||||
kCCModeGCM = 11
|
|
||||||
};
|
|
||||||
typedef uint32_t CCMode;
|
|
||||||
enum {
|
|
||||||
ccNoPadding = 0,
|
|
||||||
ccPKCS7Padding = 1,
|
|
||||||
};
|
|
||||||
typedef uint32_t CCPadding;
|
|
||||||
"""
|
|
||||||
|
|
||||||
FUNCTIONS = """
|
|
||||||
CCCryptorStatus CCCryptorCreateWithMode(CCOperation, CCMode, CCAlgorithm,
|
|
||||||
CCPadding, const void *, const void *,
|
|
||||||
size_t, const void *, size_t, int,
|
|
||||||
CCModeOptions, CCCryptorRef *);
|
|
||||||
CCCryptorStatus CCCryptorCreate(CCOperation, CCAlgorithm, CCOptions,
|
|
||||||
const void *, size_t, const void *,
|
|
||||||
CCCryptorRef *);
|
|
||||||
CCCryptorStatus CCCryptorUpdate(CCCryptorRef, const void *, size_t, void *,
|
|
||||||
size_t, size_t *);
|
|
||||||
CCCryptorStatus CCCryptorFinal(CCCryptorRef, void *, size_t, size_t *);
|
|
||||||
CCCryptorStatus CCCryptorRelease(CCCryptorRef);
|
|
||||||
|
|
||||||
CCCryptorStatus CCCryptorGCMAddIV(CCCryptorRef, const void *, size_t);
|
|
||||||
CCCryptorStatus CCCryptorGCMAddAAD(CCCryptorRef, const void *, size_t);
|
|
||||||
CCCryptorStatus CCCryptorGCMEncrypt(CCCryptorRef, const void *, size_t,
|
|
||||||
void *);
|
|
||||||
CCCryptorStatus CCCryptorGCMDecrypt(CCCryptorRef, const void *, size_t,
|
|
||||||
void *);
|
|
||||||
CCCryptorStatus CCCryptorGCMFinal(CCCryptorRef, const void *, size_t *);
|
|
||||||
CCCryptorStatus CCCryptorGCMReset(CCCryptorRef);
|
|
||||||
"""
|
|
||||||
|
|
||||||
MACROS = """
|
|
||||||
"""
|
|
||||||
|
|
||||||
CUSTOMIZATIONS = """
|
|
||||||
/* Not defined in the public header */
|
|
||||||
enum {
|
|
||||||
kCCModeGCM = 11
|
|
||||||
};
|
|
||||||
"""
|
|
||||||
|
|
||||||
CONDITIONAL_NAMES = {}
|
|
|
@ -1,69 +0,0 @@
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
# you may not use this file except in compliance with the License.
|
|
||||||
# You may obtain a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
# implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
|
||||||
|
|
||||||
INCLUDES = """
|
|
||||||
#include <CommonCrypto/CommonDigest.h>
|
|
||||||
"""
|
|
||||||
|
|
||||||
TYPES = """
|
|
||||||
typedef uint32_t CC_LONG;
|
|
||||||
typedef uint64_t CC_LONG64;
|
|
||||||
typedef struct CC_MD5state_st {
|
|
||||||
...;
|
|
||||||
} CC_MD5_CTX;
|
|
||||||
typedef struct CC_SHA1state_st {
|
|
||||||
...;
|
|
||||||
} CC_SHA1_CTX;
|
|
||||||
typedef struct CC_SHA256state_st {
|
|
||||||
...;
|
|
||||||
} CC_SHA256_CTX;
|
|
||||||
typedef struct CC_SHA512state_st {
|
|
||||||
...;
|
|
||||||
} CC_SHA512_CTX;
|
|
||||||
"""
|
|
||||||
|
|
||||||
FUNCTIONS = """
|
|
||||||
int CC_MD5_Init(CC_MD5_CTX *);
|
|
||||||
int CC_MD5_Update(CC_MD5_CTX *, const void *, CC_LONG);
|
|
||||||
int CC_MD5_Final(unsigned char *, CC_MD5_CTX *);
|
|
||||||
|
|
||||||
int CC_SHA1_Init(CC_SHA1_CTX *);
|
|
||||||
int CC_SHA1_Update(CC_SHA1_CTX *, const void *, CC_LONG);
|
|
||||||
int CC_SHA1_Final(unsigned char *, CC_SHA1_CTX *);
|
|
||||||
|
|
||||||
int CC_SHA224_Init(CC_SHA256_CTX *);
|
|
||||||
int CC_SHA224_Update(CC_SHA256_CTX *, const void *, CC_LONG);
|
|
||||||
int CC_SHA224_Final(unsigned char *, CC_SHA256_CTX *);
|
|
||||||
|
|
||||||
int CC_SHA256_Init(CC_SHA256_CTX *);
|
|
||||||
int CC_SHA256_Update(CC_SHA256_CTX *, const void *, CC_LONG);
|
|
||||||
int CC_SHA256_Final(unsigned char *, CC_SHA256_CTX *);
|
|
||||||
|
|
||||||
int CC_SHA384_Init(CC_SHA512_CTX *);
|
|
||||||
int CC_SHA384_Update(CC_SHA512_CTX *, const void *, CC_LONG);
|
|
||||||
int CC_SHA384_Final(unsigned char *, CC_SHA512_CTX *);
|
|
||||||
|
|
||||||
int CC_SHA512_Init(CC_SHA512_CTX *);
|
|
||||||
int CC_SHA512_Update(CC_SHA512_CTX *, const void *, CC_LONG);
|
|
||||||
int CC_SHA512_Final(unsigned char *, CC_SHA512_CTX *);
|
|
||||||
"""
|
|
||||||
|
|
||||||
MACROS = """
|
|
||||||
"""
|
|
||||||
|
|
||||||
CUSTOMIZATIONS = """
|
|
||||||
"""
|
|
||||||
|
|
||||||
CONDITIONAL_NAMES = {}
|
|
|
@ -1,48 +0,0 @@
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
# you may not use this file except in compliance with the License.
|
|
||||||
# You may obtain a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
# implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
|
||||||
|
|
||||||
INCLUDES = """
|
|
||||||
#include <CommonCrypto/CommonHMAC.h>
|
|
||||||
"""
|
|
||||||
|
|
||||||
TYPES = """
|
|
||||||
typedef struct {
|
|
||||||
...;
|
|
||||||
} CCHmacContext;
|
|
||||||
enum {
|
|
||||||
kCCHmacAlgSHA1,
|
|
||||||
kCCHmacAlgMD5,
|
|
||||||
kCCHmacAlgSHA256,
|
|
||||||
kCCHmacAlgSHA384,
|
|
||||||
kCCHmacAlgSHA512,
|
|
||||||
kCCHmacAlgSHA224
|
|
||||||
};
|
|
||||||
typedef uint32_t CCHmacAlgorithm;
|
|
||||||
"""
|
|
||||||
|
|
||||||
FUNCTIONS = """
|
|
||||||
void CCHmacInit(CCHmacContext *, CCHmacAlgorithm, const void *, size_t);
|
|
||||||
void CCHmacUpdate(CCHmacContext *, const void *, size_t);
|
|
||||||
void CCHmacFinal(CCHmacContext *, void *);
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
MACROS = """
|
|
||||||
"""
|
|
||||||
|
|
||||||
CUSTOMIZATIONS = """
|
|
||||||
"""
|
|
||||||
|
|
||||||
CONDITIONAL_NAMES = {}
|
|
|
@ -1,50 +0,0 @@
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
# you may not use this file except in compliance with the License.
|
|
||||||
# You may obtain a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
# implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
|
||||||
|
|
||||||
INCLUDES = """
|
|
||||||
#include <CommonCrypto/CommonKeyDerivation.h>
|
|
||||||
"""
|
|
||||||
|
|
||||||
TYPES = """
|
|
||||||
enum {
|
|
||||||
kCCPBKDF2 = 2,
|
|
||||||
};
|
|
||||||
typedef uint32_t CCPBKDFAlgorithm;
|
|
||||||
enum {
|
|
||||||
kCCPRFHmacAlgSHA1 = 1,
|
|
||||||
kCCPRFHmacAlgSHA224 = 2,
|
|
||||||
kCCPRFHmacAlgSHA256 = 3,
|
|
||||||
kCCPRFHmacAlgSHA384 = 4,
|
|
||||||
kCCPRFHmacAlgSHA512 = 5,
|
|
||||||
};
|
|
||||||
typedef uint32_t CCPseudoRandomAlgorithm;
|
|
||||||
typedef unsigned int uint;
|
|
||||||
"""
|
|
||||||
|
|
||||||
FUNCTIONS = """
|
|
||||||
int CCKeyDerivationPBKDF(CCPBKDFAlgorithm, const char *, size_t,
|
|
||||||
const uint8_t *, size_t, CCPseudoRandomAlgorithm,
|
|
||||||
uint, uint8_t *, size_t);
|
|
||||||
uint CCCalibratePBKDF(CCPBKDFAlgorithm, size_t, size_t,
|
|
||||||
CCPseudoRandomAlgorithm, size_t, uint32_t);
|
|
||||||
"""
|
|
||||||
|
|
||||||
MACROS = """
|
|
||||||
"""
|
|
||||||
|
|
||||||
CUSTOMIZATIONS = """
|
|
||||||
"""
|
|
||||||
|
|
||||||
CONDITIONAL_NAMES = {}
|
|
|
@ -1,95 +0,0 @@
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
# you may not use this file except in compliance with the License.
|
|
||||||
# You may obtain a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
# implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
|
||||||
|
|
||||||
INCLUDES = """
|
|
||||||
#include <Security/SecImportExport.h>
|
|
||||||
"""
|
|
||||||
|
|
||||||
TYPES = """
|
|
||||||
typedef ... *SecAccessRef;
|
|
||||||
|
|
||||||
CFStringRef kSecImportExportPassphrase;
|
|
||||||
CFStringRef kSecImportExportKeychain;
|
|
||||||
CFStringRef kSecImportExportAccess;
|
|
||||||
|
|
||||||
typedef uint32_t SecExternalItemType;
|
|
||||||
enum {
|
|
||||||
kSecItemTypeUnknown,
|
|
||||||
kSecItemTypePrivateKey,
|
|
||||||
kSecItemTypePublicKey,
|
|
||||||
kSecItemTypeSessionKey,
|
|
||||||
kSecItemTypeCertificate,
|
|
||||||
kSecItemTypeAggregate
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
typedef uint32_t SecExternalFormat;
|
|
||||||
enum {
|
|
||||||
kSecFormatUnknown = 0,
|
|
||||||
kSecFormatOpenSSL,
|
|
||||||
kSecFormatSSH,
|
|
||||||
kSecFormatBSAFE,
|
|
||||||
kSecFormatRawKey,
|
|
||||||
kSecFormatWrappedPKCS8,
|
|
||||||
kSecFormatWrappedOpenSSL,
|
|
||||||
kSecFormatWrappedSSH,
|
|
||||||
kSecFormatWrappedLSH,
|
|
||||||
kSecFormatX509Cert,
|
|
||||||
kSecFormatPEMSequence,
|
|
||||||
kSecFormatPKCS7,
|
|
||||||
kSecFormatPKCS12,
|
|
||||||
kSecFormatNetscapeCertSequence,
|
|
||||||
kSecFormatSSHv2
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef uint32_t SecItemImportExportFlags;
|
|
||||||
enum {
|
|
||||||
kSecKeyImportOnlyOne = 0x00000001,
|
|
||||||
kSecKeySecurePassphrase = 0x00000002,
|
|
||||||
kSecKeyNoAccessControl = 0x00000004
|
|
||||||
};
|
|
||||||
typedef uint32_t SecKeyImportExportFlags;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
/* for import and export */
|
|
||||||
uint32_t version;
|
|
||||||
SecKeyImportExportFlags flags;
|
|
||||||
CFTypeRef passphrase;
|
|
||||||
CFStringRef alertTitle;
|
|
||||||
CFStringRef alertPrompt;
|
|
||||||
|
|
||||||
/* for import only */
|
|
||||||
SecAccessRef accessRef;
|
|
||||||
CFArrayRef keyUsage;
|
|
||||||
|
|
||||||
CFArrayRef keyAttributes;
|
|
||||||
} SecItemImportExportKeyParameters;
|
|
||||||
"""
|
|
||||||
|
|
||||||
FUNCTIONS = """
|
|
||||||
OSStatus SecItemImport(CFDataRef, CFStringRef, SecExternalFormat *,
|
|
||||||
SecExternalItemType *, SecItemImportExportFlags,
|
|
||||||
const SecItemImportExportKeyParameters *,
|
|
||||||
SecKeychainRef, CFArrayRef *);
|
|
||||||
OSStatus SecPKCS12Import(CFDataRef, CFDictionaryRef, CFArrayRef *);
|
|
||||||
"""
|
|
||||||
|
|
||||||
MACROS = """
|
|
||||||
"""
|
|
||||||
|
|
||||||
CUSTOMIZATIONS = """
|
|
||||||
"""
|
|
||||||
|
|
||||||
CONDITIONAL_NAMES = {}
|
|
|
@ -1,38 +0,0 @@
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
# you may not use this file except in compliance with the License.
|
|
||||||
# You may obtain a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
# implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
|
||||||
|
|
||||||
INCLUDES = """
|
|
||||||
#include <Security/SecItem.h>
|
|
||||||
"""
|
|
||||||
|
|
||||||
TYPES = """
|
|
||||||
const CFTypeRef kSecAttrKeyType;
|
|
||||||
const CFTypeRef kSecAttrKeySizeInBits;
|
|
||||||
const CFTypeRef kSecAttrIsPermanent;
|
|
||||||
const CFTypeRef kSecAttrKeyTypeRSA;
|
|
||||||
const CFTypeRef kSecAttrKeyTypeDSA;
|
|
||||||
const CFTypeRef kSecUseKeychain;
|
|
||||||
"""
|
|
||||||
|
|
||||||
FUNCTIONS = """
|
|
||||||
"""
|
|
||||||
|
|
||||||
MACROS = """
|
|
||||||
"""
|
|
||||||
|
|
||||||
CUSTOMIZATIONS = """
|
|
||||||
"""
|
|
||||||
|
|
||||||
CONDITIONAL_NAMES = {}
|
|
|
@ -1,35 +0,0 @@
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
# you may not use this file except in compliance with the License.
|
|
||||||
# You may obtain a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
# implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
|
||||||
|
|
||||||
INCLUDES = """
|
|
||||||
#include <Security/SecKey.h>
|
|
||||||
"""
|
|
||||||
|
|
||||||
TYPES = """
|
|
||||||
typedef ... *SecKeyRef;
|
|
||||||
"""
|
|
||||||
|
|
||||||
FUNCTIONS = """
|
|
||||||
OSStatus SecKeyGeneratePair(CFDictionaryRef, SecKeyRef *, SecKeyRef *);
|
|
||||||
size_t SecKeyGetBlockSize(SecKeyRef);
|
|
||||||
"""
|
|
||||||
|
|
||||||
MACROS = """
|
|
||||||
"""
|
|
||||||
|
|
||||||
CUSTOMIZATIONS = """
|
|
||||||
"""
|
|
||||||
|
|
||||||
CONDITIONAL_NAMES = {}
|
|
|
@ -1,36 +0,0 @@
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
# you may not use this file except in compliance with the License.
|
|
||||||
# You may obtain a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
# implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
|
||||||
|
|
||||||
INCLUDES = """
|
|
||||||
#include <Security/SecKeychain.h>
|
|
||||||
"""
|
|
||||||
|
|
||||||
TYPES = """
|
|
||||||
typedef ... *SecKeychainRef;
|
|
||||||
"""
|
|
||||||
|
|
||||||
FUNCTIONS = """
|
|
||||||
OSStatus SecKeychainCreate(const char *, UInt32, const void *, Boolean,
|
|
||||||
SecAccessRef, SecKeychainRef *);
|
|
||||||
OSStatus SecKeychainDelete(SecKeychainRef);
|
|
||||||
"""
|
|
||||||
|
|
||||||
MACROS = """
|
|
||||||
"""
|
|
||||||
|
|
||||||
CUSTOMIZATIONS = """
|
|
||||||
"""
|
|
||||||
|
|
||||||
CONDITIONAL_NAMES = {}
|
|
|
@ -1,79 +0,0 @@
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
# you may not use this file except in compliance with the License.
|
|
||||||
# You may obtain a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
# implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
|
||||||
|
|
||||||
INCLUDES = """
|
|
||||||
#include <Security/SecDigestTransform.h>
|
|
||||||
#include <Security/SecSignVerifyTransform.h>
|
|
||||||
#include <Security/SecEncryptTransform.h>
|
|
||||||
"""
|
|
||||||
|
|
||||||
TYPES = """
|
|
||||||
typedef ... *SecTransformRef;
|
|
||||||
|
|
||||||
CFStringRef kSecImportExportPassphrase;
|
|
||||||
CFStringRef kSecImportExportKeychain;
|
|
||||||
CFStringRef kSecImportExportAccess;
|
|
||||||
|
|
||||||
CFStringRef kSecEncryptionMode;
|
|
||||||
CFStringRef kSecEncryptKey;
|
|
||||||
CFStringRef kSecIVKey;
|
|
||||||
CFStringRef kSecModeCBCKey;
|
|
||||||
CFStringRef kSecModeCFBKey;
|
|
||||||
CFStringRef kSecModeECBKey;
|
|
||||||
CFStringRef kSecModeNoneKey;
|
|
||||||
CFStringRef kSecModeOFBKey;
|
|
||||||
CFStringRef kSecOAEPEncodingParametersAttributeName;
|
|
||||||
CFStringRef kSecPaddingKey;
|
|
||||||
CFStringRef kSecPaddingNoneKey;
|
|
||||||
CFStringRef kSecPaddingOAEPKey;
|
|
||||||
CFStringRef kSecPaddingPKCS1Key;
|
|
||||||
CFStringRef kSecPaddingPKCS5Key;
|
|
||||||
CFStringRef kSecPaddingPKCS7Key;
|
|
||||||
|
|
||||||
const CFStringRef kSecTransformInputAttributeName;
|
|
||||||
const CFStringRef kSecTransformOutputAttributeName;
|
|
||||||
const CFStringRef kSecTransformDebugAttributeName;
|
|
||||||
const CFStringRef kSecTransformTransformName;
|
|
||||||
const CFStringRef kSecTransformAbortAttributeName;
|
|
||||||
|
|
||||||
CFStringRef kSecInputIsAttributeName;
|
|
||||||
CFStringRef kSecInputIsPlainText;
|
|
||||||
CFStringRef kSecInputIsDigest;
|
|
||||||
CFStringRef kSecInputIsRaw;
|
|
||||||
|
|
||||||
const CFStringRef kSecDigestTypeAttribute;
|
|
||||||
const CFStringRef kSecDigestLengthAttribute;
|
|
||||||
const CFStringRef kSecDigestMD5;
|
|
||||||
const CFStringRef kSecDigestSHA1;
|
|
||||||
const CFStringRef kSecDigestSHA2;
|
|
||||||
"""
|
|
||||||
|
|
||||||
FUNCTIONS = """
|
|
||||||
Boolean SecTransformSetAttribute(SecTransformRef, CFStringRef, CFTypeRef,
|
|
||||||
CFErrorRef *);
|
|
||||||
SecTransformRef SecDecryptTransformCreate(SecKeyRef, CFErrorRef *);
|
|
||||||
SecTransformRef SecEncryptTransformCreate(SecKeyRef, CFErrorRef *);
|
|
||||||
SecTransformRef SecVerifyTransformCreate(SecKeyRef, CFDataRef, CFErrorRef *);
|
|
||||||
SecTransformRef SecSignTransformCreate(SecKeyRef, CFErrorRef *) ;
|
|
||||||
CFTypeRef SecTransformExecute(SecTransformRef, CFErrorRef *);
|
|
||||||
"""
|
|
||||||
|
|
||||||
MACROS = """
|
|
||||||
"""
|
|
||||||
|
|
||||||
CUSTOMIZATIONS = """
|
|
||||||
"""
|
|
||||||
|
|
||||||
CONDITIONAL_NAMES = {}
|
|
|
@ -1,14 +1,5 @@
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# This file is dual licensed under the terms of the Apache License, Version
|
||||||
# you may not use this file except in compliance with the License.
|
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
|
||||||
# You may obtain a copy of the License at
|
# for complete details.
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
# implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
|
@ -0,0 +1,418 @@
|
||||||
|
# This file is dual licensed under the terms of the Apache License, Version
|
||||||
|
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
|
||||||
|
# for complete details.
|
||||||
|
|
||||||
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
|
# This is a temporary copy of all the CONDITIONAL_NAMES from _cffi_src so
|
||||||
|
# we can loop over them and delete them at runtime. It will be removed when
|
||||||
|
# cffi supports #if in cdef
|
||||||
|
|
||||||
|
CONDITIONAL_NAMES = {
|
||||||
|
"Cryptography_HAS_AES_WRAP": [
|
||||||
|
"AES_wrap_key",
|
||||||
|
"AES_unwrap_key",
|
||||||
|
],
|
||||||
|
"Cryptography_HAS_CMAC": [
|
||||||
|
"CMAC_CTX_new",
|
||||||
|
"CMAC_Init",
|
||||||
|
"CMAC_Update",
|
||||||
|
"CMAC_Final",
|
||||||
|
"CMAC_CTX_copy",
|
||||||
|
"CMAC_CTX_free",
|
||||||
|
],
|
||||||
|
"Cryptography_HAS_CMS": [
|
||||||
|
"BIO_new_CMS",
|
||||||
|
"i2d_CMS_bio_stream",
|
||||||
|
"PEM_write_bio_CMS_stream",
|
||||||
|
"CMS_final",
|
||||||
|
"CMS_sign",
|
||||||
|
"CMS_verify",
|
||||||
|
"CMS_encrypt",
|
||||||
|
"CMS_decrypt",
|
||||||
|
"CMS_add1_signer",
|
||||||
|
"CMS_TEXT",
|
||||||
|
"CMS_NOCERTS",
|
||||||
|
"CMS_NO_CONTENT_VERIFY",
|
||||||
|
"CMS_NO_ATTR_VERIFY",
|
||||||
|
"CMS_NOSIGS",
|
||||||
|
"CMS_NOINTERN",
|
||||||
|
"CMS_NO_SIGNER_CERT_VERIFY",
|
||||||
|
"CMS_NOVERIFY",
|
||||||
|
"CMS_DETACHED",
|
||||||
|
"CMS_BINARY",
|
||||||
|
"CMS_NOATTR",
|
||||||
|
"CMS_NOSMIMECAP",
|
||||||
|
"CMS_NOOLDMIMETYPE",
|
||||||
|
"CMS_CRLFEOL",
|
||||||
|
"CMS_STREAM",
|
||||||
|
"CMS_NOCRL",
|
||||||
|
"CMS_PARTIAL",
|
||||||
|
"CMS_REUSE_DIGEST",
|
||||||
|
"CMS_USE_KEYID",
|
||||||
|
"CMS_DEBUG_DECRYPT",
|
||||||
|
],
|
||||||
|
"Cryptography_HAS_EC": [
|
||||||
|
"OPENSSL_EC_NAMED_CURVE",
|
||||||
|
"EC_GROUP_new",
|
||||||
|
"EC_GROUP_free",
|
||||||
|
"EC_GROUP_clear_free",
|
||||||
|
"EC_GROUP_new_curve_GFp",
|
||||||
|
"EC_GROUP_new_by_curve_name",
|
||||||
|
"EC_GROUP_set_curve_GFp",
|
||||||
|
"EC_GROUP_get_curve_GFp",
|
||||||
|
"EC_GROUP_method_of",
|
||||||
|
"EC_GROUP_get0_generator",
|
||||||
|
"EC_GROUP_get_curve_name",
|
||||||
|
"EC_GROUP_get_degree",
|
||||||
|
"EC_GROUP_set_asn1_flag",
|
||||||
|
"EC_GROUP_set_point_conversion_form",
|
||||||
|
"EC_KEY_new",
|
||||||
|
"EC_KEY_free",
|
||||||
|
"EC_get_builtin_curves",
|
||||||
|
"EC_KEY_new_by_curve_name",
|
||||||
|
"EC_KEY_copy",
|
||||||
|
"EC_KEY_dup",
|
||||||
|
"EC_KEY_up_ref",
|
||||||
|
"EC_KEY_set_group",
|
||||||
|
"EC_KEY_get0_private_key",
|
||||||
|
"EC_KEY_set_private_key",
|
||||||
|
"EC_KEY_set_public_key",
|
||||||
|
"EC_KEY_get_enc_flags",
|
||||||
|
"EC_KEY_set_enc_flags",
|
||||||
|
"EC_KEY_set_conv_form",
|
||||||
|
"EC_KEY_get_key_method_data",
|
||||||
|
"EC_KEY_insert_key_method_data",
|
||||||
|
"EC_KEY_set_asn1_flag",
|
||||||
|
"EC_KEY_precompute_mult",
|
||||||
|
"EC_KEY_generate_key",
|
||||||
|
"EC_KEY_check_key",
|
||||||
|
"EC_POINT_new",
|
||||||
|
"EC_POINT_free",
|
||||||
|
"EC_POINT_clear_free",
|
||||||
|
"EC_POINT_copy",
|
||||||
|
"EC_POINT_dup",
|
||||||
|
"EC_POINT_method_of",
|
||||||
|
"EC_POINT_set_to_infinity",
|
||||||
|
"EC_POINT_set_Jprojective_coordinates_GFp",
|
||||||
|
"EC_POINT_get_Jprojective_coordinates_GFp",
|
||||||
|
"EC_POINT_set_affine_coordinates_GFp",
|
||||||
|
"EC_POINT_get_affine_coordinates_GFp",
|
||||||
|
"EC_POINT_set_compressed_coordinates_GFp",
|
||||||
|
"EC_POINT_point2oct",
|
||||||
|
"EC_POINT_oct2point",
|
||||||
|
"EC_POINT_point2bn",
|
||||||
|
"EC_POINT_bn2point",
|
||||||
|
"EC_POINT_point2hex",
|
||||||
|
"EC_POINT_hex2point",
|
||||||
|
"EC_POINT_add",
|
||||||
|
"EC_POINT_dbl",
|
||||||
|
"EC_POINT_invert",
|
||||||
|
"EC_POINT_is_at_infinity",
|
||||||
|
"EC_POINT_is_on_curve",
|
||||||
|
"EC_POINT_cmp",
|
||||||
|
"EC_POINT_make_affine",
|
||||||
|
"EC_POINTs_make_affine",
|
||||||
|
"EC_POINTs_mul",
|
||||||
|
"EC_POINT_mul",
|
||||||
|
"EC_GROUP_precompute_mult",
|
||||||
|
"EC_GROUP_have_precompute_mult",
|
||||||
|
"EC_GFp_simple_method",
|
||||||
|
"EC_GFp_mont_method",
|
||||||
|
"EC_GFp_nist_method",
|
||||||
|
"EC_METHOD_get_field_type",
|
||||||
|
"EVP_PKEY_assign_EC_KEY",
|
||||||
|
"EVP_PKEY_get1_EC_KEY",
|
||||||
|
"EVP_PKEY_set1_EC_KEY",
|
||||||
|
"PEM_write_bio_ECPrivateKey",
|
||||||
|
"i2d_EC_PUBKEY",
|
||||||
|
"d2i_EC_PUBKEY",
|
||||||
|
"d2i_EC_PUBKEY_bio",
|
||||||
|
"i2d_EC_PUBKEY_bio",
|
||||||
|
"d2i_ECPrivateKey",
|
||||||
|
"d2i_ECPrivateKey_bio",
|
||||||
|
"i2d_ECPrivateKey",
|
||||||
|
"i2d_ECPrivateKey_bio",
|
||||||
|
"i2o_ECPublicKey",
|
||||||
|
"o2i_ECPublicKey",
|
||||||
|
"SSL_CTX_set_tmp_ecdh",
|
||||||
|
],
|
||||||
|
|
||||||
|
"Cryptography_HAS_EC_1_0_1": [
|
||||||
|
"EC_KEY_get_flags",
|
||||||
|
"EC_KEY_set_flags",
|
||||||
|
"EC_KEY_clear_flags",
|
||||||
|
"EC_KEY_set_public_key_affine_coordinates",
|
||||||
|
],
|
||||||
|
|
||||||
|
"Cryptography_HAS_EC_NISTP_64_GCC_128": [
|
||||||
|
"EC_GFp_nistp224_method",
|
||||||
|
"EC_GFp_nistp256_method",
|
||||||
|
"EC_GFp_nistp521_method",
|
||||||
|
],
|
||||||
|
|
||||||
|
"Cryptography_HAS_EC2M": [
|
||||||
|
"EC_GF2m_simple_method",
|
||||||
|
"EC_POINT_set_affine_coordinates_GF2m",
|
||||||
|
"EC_POINT_get_affine_coordinates_GF2m",
|
||||||
|
"EC_POINT_set_compressed_coordinates_GF2m",
|
||||||
|
"EC_GROUP_set_curve_GF2m",
|
||||||
|
"EC_GROUP_get_curve_GF2m",
|
||||||
|
"EC_GROUP_new_curve_GF2m",
|
||||||
|
],
|
||||||
|
|
||||||
|
"Cryptography_HAS_EC_1_0_2": [
|
||||||
|
"EC_curve_nid2nist",
|
||||||
|
],
|
||||||
|
"Cryptography_HAS_ECDH": [
|
||||||
|
"ECDH_compute_key",
|
||||||
|
"ECDH_get_ex_new_index",
|
||||||
|
"ECDH_set_ex_data",
|
||||||
|
"ECDH_get_ex_data",
|
||||||
|
],
|
||||||
|
"Cryptography_HAS_ECDSA": [
|
||||||
|
"ECDSA_SIG_new",
|
||||||
|
"ECDSA_SIG_free",
|
||||||
|
"i2d_ECDSA_SIG",
|
||||||
|
"d2i_ECDSA_SIG",
|
||||||
|
"ECDSA_do_sign",
|
||||||
|
"ECDSA_do_sign_ex",
|
||||||
|
"ECDSA_do_verify",
|
||||||
|
"ECDSA_sign_setup",
|
||||||
|
"ECDSA_sign",
|
||||||
|
"ECDSA_sign_ex",
|
||||||
|
"ECDSA_verify",
|
||||||
|
"ECDSA_size",
|
||||||
|
"ECDSA_OpenSSL",
|
||||||
|
"ECDSA_set_default_method",
|
||||||
|
"ECDSA_get_default_method",
|
||||||
|
"ECDSA_set_method",
|
||||||
|
"ECDSA_get_ex_new_index",
|
||||||
|
"ECDSA_set_ex_data",
|
||||||
|
"ECDSA_get_ex_data",
|
||||||
|
],
|
||||||
|
"Cryptography_HAS_ENGINE_CRYPTODEV": [
|
||||||
|
"ENGINE_load_cryptodev"
|
||||||
|
],
|
||||||
|
"Cryptography_HAS_REMOVE_THREAD_STATE": [
|
||||||
|
"ERR_remove_thread_state"
|
||||||
|
],
|
||||||
|
"Cryptography_HAS_098H_ERROR_CODES": [
|
||||||
|
"ASN1_F_B64_READ_ASN1",
|
||||||
|
"ASN1_F_B64_WRITE_ASN1",
|
||||||
|
"ASN1_F_SMIME_READ_ASN1",
|
||||||
|
"ASN1_F_SMIME_TEXT",
|
||||||
|
"ASN1_R_NO_CONTENT_TYPE",
|
||||||
|
"ASN1_R_NO_MULTIPART_BODY_FAILURE",
|
||||||
|
"ASN1_R_NO_MULTIPART_BOUNDARY",
|
||||||
|
],
|
||||||
|
"Cryptography_HAS_098C_CAMELLIA_CODES": [
|
||||||
|
"EVP_F_CAMELLIA_INIT_KEY",
|
||||||
|
"EVP_R_CAMELLIA_KEY_SETUP_FAILED"
|
||||||
|
],
|
||||||
|
"Cryptography_HAS_EC_CODES": [
|
||||||
|
"EC_R_UNKNOWN_GROUP",
|
||||||
|
"EC_F_EC_GROUP_NEW_BY_CURVE_NAME"
|
||||||
|
],
|
||||||
|
"Cryptography_HAS_RSA_R_PKCS_DECODING_ERROR": [
|
||||||
|
"RSA_R_PKCS_DECODING_ERROR"
|
||||||
|
],
|
||||||
|
"Cryptography_HAS_GCM": [
|
||||||
|
"EVP_CTRL_GCM_GET_TAG",
|
||||||
|
"EVP_CTRL_GCM_SET_TAG",
|
||||||
|
"EVP_CTRL_GCM_SET_IVLEN",
|
||||||
|
],
|
||||||
|
"Cryptography_HAS_PBKDF2_HMAC": [
|
||||||
|
"PKCS5_PBKDF2_HMAC"
|
||||||
|
],
|
||||||
|
"Cryptography_HAS_PKEY_CTX": [
|
||||||
|
"EVP_PKEY_CTX_new",
|
||||||
|
"EVP_PKEY_CTX_new_id",
|
||||||
|
"EVP_PKEY_CTX_dup",
|
||||||
|
"EVP_PKEY_CTX_free",
|
||||||
|
"EVP_PKEY_sign",
|
||||||
|
"EVP_PKEY_sign_init",
|
||||||
|
"EVP_PKEY_verify",
|
||||||
|
"EVP_PKEY_verify_init",
|
||||||
|
"Cryptography_EVP_PKEY_encrypt",
|
||||||
|
"EVP_PKEY_encrypt_init",
|
||||||
|
"Cryptography_EVP_PKEY_decrypt",
|
||||||
|
"EVP_PKEY_decrypt_init",
|
||||||
|
"EVP_PKEY_CTX_set_signature_md",
|
||||||
|
"EVP_PKEY_id",
|
||||||
|
"EVP_PKEY_CTX_set_rsa_padding",
|
||||||
|
"EVP_PKEY_CTX_set_rsa_pss_saltlen",
|
||||||
|
],
|
||||||
|
"Cryptography_HAS_ECDSA_SHA2_NIDS": [
|
||||||
|
"NID_ecdsa_with_SHA224",
|
||||||
|
"NID_ecdsa_with_SHA256",
|
||||||
|
"NID_ecdsa_with_SHA384",
|
||||||
|
"NID_ecdsa_with_SHA512",
|
||||||
|
],
|
||||||
|
"Cryptography_HAS_EGD": [
|
||||||
|
"RAND_egd",
|
||||||
|
"RAND_egd_bytes",
|
||||||
|
"RAND_query_egd_bytes",
|
||||||
|
],
|
||||||
|
"Cryptography_HAS_PSS_PADDING": [
|
||||||
|
"RSA_PKCS1_PSS_PADDING",
|
||||||
|
],
|
||||||
|
"Cryptography_HAS_MGF1_MD": [
|
||||||
|
"EVP_PKEY_CTX_set_rsa_mgf1_md",
|
||||||
|
],
|
||||||
|
"Cryptography_HAS_TLSv1_1": [
|
||||||
|
"SSL_OP_NO_TLSv1_1",
|
||||||
|
"TLSv1_1_method",
|
||||||
|
"TLSv1_1_server_method",
|
||||||
|
"TLSv1_1_client_method",
|
||||||
|
],
|
||||||
|
|
||||||
|
"Cryptography_HAS_TLSv1_2": [
|
||||||
|
"SSL_OP_NO_TLSv1_2",
|
||||||
|
"TLSv1_2_method",
|
||||||
|
"TLSv1_2_server_method",
|
||||||
|
"TLSv1_2_client_method",
|
||||||
|
],
|
||||||
|
|
||||||
|
"Cryptography_HAS_SSL2": [
|
||||||
|
"SSLv2_method",
|
||||||
|
"SSLv2_client_method",
|
||||||
|
"SSLv2_server_method",
|
||||||
|
],
|
||||||
|
|
||||||
|
"Cryptography_HAS_SSL3_METHOD": [
|
||||||
|
"SSLv3_method",
|
||||||
|
"SSLv3_client_method",
|
||||||
|
"SSLv3_server_method",
|
||||||
|
],
|
||||||
|
|
||||||
|
"Cryptography_HAS_TLSEXT_HOSTNAME": [
|
||||||
|
"SSL_set_tlsext_host_name",
|
||||||
|
"SSL_get_servername",
|
||||||
|
"SSL_CTX_set_tlsext_servername_callback",
|
||||||
|
],
|
||||||
|
|
||||||
|
"Cryptography_HAS_TLSEXT_STATUS_REQ_CB": [
|
||||||
|
"SSL_CTX_set_tlsext_status_cb",
|
||||||
|
"SSL_CTX_set_tlsext_status_arg"
|
||||||
|
],
|
||||||
|
|
||||||
|
"Cryptography_HAS_STATUS_REQ_OCSP_RESP": [
|
||||||
|
"SSL_set_tlsext_status_ocsp_resp",
|
||||||
|
"SSL_get_tlsext_status_ocsp_resp",
|
||||||
|
],
|
||||||
|
|
||||||
|
"Cryptography_HAS_TLSEXT_STATUS_REQ_TYPE": [
|
||||||
|
"SSL_set_tlsext_status_type",
|
||||||
|
],
|
||||||
|
|
||||||
|
"Cryptography_HAS_RELEASE_BUFFERS": [
|
||||||
|
"SSL_MODE_RELEASE_BUFFERS",
|
||||||
|
],
|
||||||
|
|
||||||
|
"Cryptography_HAS_OP_NO_COMPRESSION": [
|
||||||
|
"SSL_OP_NO_COMPRESSION",
|
||||||
|
],
|
||||||
|
|
||||||
|
"Cryptography_HAS_SSL_OP_MSIE_SSLV2_RSA_PADDING": [
|
||||||
|
"SSL_OP_MSIE_SSLV2_RSA_PADDING",
|
||||||
|
],
|
||||||
|
|
||||||
|
"Cryptography_HAS_SSL_OP_NO_TICKET": [
|
||||||
|
"SSL_OP_NO_TICKET",
|
||||||
|
],
|
||||||
|
|
||||||
|
"Cryptography_HAS_SSL_SET_SSL_CTX": [
|
||||||
|
"SSL_set_SSL_CTX",
|
||||||
|
"TLSEXT_NAMETYPE_host_name",
|
||||||
|
],
|
||||||
|
|
||||||
|
"Cryptography_HAS_NETBSD_D1_METH": [
|
||||||
|
"DTLSv1_method",
|
||||||
|
],
|
||||||
|
|
||||||
|
"Cryptography_HAS_NEXTPROTONEG": [
|
||||||
|
"SSL_CTX_set_next_protos_advertised_cb",
|
||||||
|
"SSL_CTX_set_next_proto_select_cb",
|
||||||
|
"SSL_select_next_proto",
|
||||||
|
"SSL_get0_next_proto_negotiated",
|
||||||
|
],
|
||||||
|
|
||||||
|
"Cryptography_HAS_SECURE_RENEGOTIATION": [
|
||||||
|
"SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION",
|
||||||
|
"SSL_OP_LEGACY_SERVER_CONNECT",
|
||||||
|
"SSL_get_secure_renegotiation_support",
|
||||||
|
],
|
||||||
|
|
||||||
|
"Cryptography_HAS_ALPN": [
|
||||||
|
"SSL_CTX_set_alpn_protos",
|
||||||
|
"SSL_set_alpn_protos",
|
||||||
|
"SSL_CTX_set_alpn_select_cb",
|
||||||
|
"SSL_get0_alpn_selected",
|
||||||
|
],
|
||||||
|
|
||||||
|
"Cryptography_HAS_COMPRESSION": [
|
||||||
|
"SSL_get_current_compression",
|
||||||
|
"SSL_get_current_expansion",
|
||||||
|
"SSL_COMP_get_name",
|
||||||
|
],
|
||||||
|
|
||||||
|
"Cryptography_HAS_GET_SERVER_TMP_KEY": [
|
||||||
|
"SSL_get_server_tmp_key",
|
||||||
|
],
|
||||||
|
|
||||||
|
"Cryptography_HAS_SSL_CTX_SET_CLIENT_CERT_ENGINE": [
|
||||||
|
"SSL_CTX_set_client_cert_engine",
|
||||||
|
],
|
||||||
|
"Cryptography_HAS_102_VERIFICATION_ERROR_CODES": [
|
||||||
|
'X509_V_ERR_SUITE_B_INVALID_VERSION',
|
||||||
|
'X509_V_ERR_SUITE_B_INVALID_ALGORITHM',
|
||||||
|
'X509_V_ERR_SUITE_B_INVALID_CURVE',
|
||||||
|
'X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM',
|
||||||
|
'X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED',
|
||||||
|
'X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256',
|
||||||
|
'X509_V_ERR_HOSTNAME_MISMATCH',
|
||||||
|
'X509_V_ERR_EMAIL_MISMATCH',
|
||||||
|
'X509_V_ERR_IP_ADDRESS_MISMATCH'
|
||||||
|
],
|
||||||
|
"Cryptography_HAS_102_VERIFICATION_PARAMS": [
|
||||||
|
"X509_V_FLAG_SUITEB_128_LOS_ONLY",
|
||||||
|
"X509_V_FLAG_SUITEB_192_LOS",
|
||||||
|
"X509_V_FLAG_SUITEB_128_LOS",
|
||||||
|
"X509_VERIFY_PARAM_set1_host",
|
||||||
|
"X509_VERIFY_PARAM_set1_email",
|
||||||
|
"X509_VERIFY_PARAM_set1_ip",
|
||||||
|
"X509_VERIFY_PARAM_set1_ip_asc",
|
||||||
|
"X509_VERIFY_PARAM_set_hostflags",
|
||||||
|
],
|
||||||
|
"Cryptography_HAS_X509_V_FLAG_TRUSTED_FIRST": [
|
||||||
|
"X509_V_FLAG_TRUSTED_FIRST",
|
||||||
|
],
|
||||||
|
"Cryptography_HAS_X509_V_FLAG_PARTIAL_CHAIN": [
|
||||||
|
"X509_V_FLAG_PARTIAL_CHAIN",
|
||||||
|
],
|
||||||
|
"Cryptography_HAS_100_VERIFICATION_ERROR_CODES": [
|
||||||
|
'X509_V_ERR_DIFFERENT_CRL_SCOPE',
|
||||||
|
'X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE',
|
||||||
|
'X509_V_ERR_UNNESTED_RESOURCE',
|
||||||
|
'X509_V_ERR_PERMITTED_VIOLATION',
|
||||||
|
'X509_V_ERR_EXCLUDED_VIOLATION',
|
||||||
|
'X509_V_ERR_SUBTREE_MINMAX',
|
||||||
|
'X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE',
|
||||||
|
'X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX',
|
||||||
|
'X509_V_ERR_UNSUPPORTED_NAME_SYNTAX',
|
||||||
|
'X509_V_ERR_CRL_PATH_VALIDATION_ERROR',
|
||||||
|
],
|
||||||
|
"Cryptography_HAS_100_VERIFICATION_PARAMS": [
|
||||||
|
"Cryptography_HAS_100_VERIFICATION_PARAMS",
|
||||||
|
"X509_V_FLAG_EXTENDED_CRL_SUPPORT",
|
||||||
|
"X509_V_FLAG_USE_DELTAS",
|
||||||
|
],
|
||||||
|
"Cryptography_HAS_X509_V_FLAG_CHECK_SS_SIGNATURE": [
|
||||||
|
"X509_V_FLAG_CHECK_SS_SIGNATURE",
|
||||||
|
],
|
||||||
|
"Cryptography_HAS_SET_CERT_CB": [
|
||||||
|
"SSL_CTX_set_cert_cb",
|
||||||
|
"SSL_set_cert_cb",
|
||||||
|
],
|
||||||
|
}
|
|
@ -1,70 +0,0 @@
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
# you may not use this file except in compliance with the License.
|
|
||||||
# You may obtain a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
# implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
|
||||||
|
|
||||||
INCLUDES = """
|
|
||||||
#include <openssl/aes.h>
|
|
||||||
"""
|
|
||||||
|
|
||||||
TYPES = """
|
|
||||||
static const int Cryptography_HAS_AES_WRAP;
|
|
||||||
|
|
||||||
struct aes_key_st {
|
|
||||||
...;
|
|
||||||
};
|
|
||||||
typedef struct aes_key_st AES_KEY;
|
|
||||||
"""
|
|
||||||
|
|
||||||
FUNCTIONS = """
|
|
||||||
int AES_set_encrypt_key(const unsigned char *, const int, AES_KEY *);
|
|
||||||
int AES_set_decrypt_key(const unsigned char *, const int, AES_KEY *);
|
|
||||||
"""
|
|
||||||
|
|
||||||
MACROS = """
|
|
||||||
/* these can be moved back to FUNCTIONS once we drop support for 0.9.8h.
|
|
||||||
This should be when we drop RHEL/CentOS 5, which is on 0.9.8e. */
|
|
||||||
int AES_wrap_key(AES_KEY *, const unsigned char *, unsigned char *,
|
|
||||||
const unsigned char *, unsigned int);
|
|
||||||
int AES_unwrap_key(AES_KEY *, const unsigned char *, unsigned char *,
|
|
||||||
const unsigned char *, unsigned int);
|
|
||||||
|
|
||||||
/* The ctr128_encrypt function is only useful in 0.9.8. You should use EVP for
|
|
||||||
this in 1.0.0+. It is defined in macros because the function signature
|
|
||||||
changed after 0.9.8 */
|
|
||||||
void AES_ctr128_encrypt(const unsigned char *, unsigned char *,
|
|
||||||
const size_t, const AES_KEY *,
|
|
||||||
unsigned char[], unsigned char[], unsigned int *);
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
CUSTOMIZATIONS = """
|
|
||||||
/* OpenSSL 0.9.8h+ */
|
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x0090808fL
|
|
||||||
static const long Cryptography_HAS_AES_WRAP = 1;
|
|
||||||
#else
|
|
||||||
static const long Cryptography_HAS_AES_WRAP = 0;
|
|
||||||
int (*AES_wrap_key)(AES_KEY *, const unsigned char *, unsigned char *,
|
|
||||||
const unsigned char *, unsigned int) = NULL;
|
|
||||||
int (*AES_unwrap_key)(AES_KEY *, const unsigned char *, unsigned char *,
|
|
||||||
const unsigned char *, unsigned int) = NULL;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
CONDITIONAL_NAMES = {
|
|
||||||
"Cryptography_HAS_AES_WRAP": [
|
|
||||||
"AES_wrap_key",
|
|
||||||
"AES_unwrap_key",
|
|
||||||
],
|
|
||||||
}
|
|
|
@ -1,152 +0,0 @@
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
# you may not use this file except in compliance with the License.
|
|
||||||
# You may obtain a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
# implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
|
||||||
|
|
||||||
INCLUDES = """
|
|
||||||
#include <openssl/asn1.h>
|
|
||||||
"""
|
|
||||||
|
|
||||||
TYPES = """
|
|
||||||
/*
|
|
||||||
* TODO: This typedef is wrong.
|
|
||||||
*
|
|
||||||
* This is due to limitations of cffi.
|
|
||||||
* See https://bitbucket.org/cffi/cffi/issue/69
|
|
||||||
*
|
|
||||||
* For another possible work-around (not used here because it involves more
|
|
||||||
* complicated use of the cffi API which falls outside the general pattern used
|
|
||||||
* by this package), see
|
|
||||||
* http://paste.pound-python.org/show/iJcTUMkKeBeS6yXpZWUU/
|
|
||||||
*
|
|
||||||
* The work-around used here is to just be sure to declare a type that is at
|
|
||||||
* least as large as the real type. Maciej explains:
|
|
||||||
*
|
|
||||||
* <fijal> I think you want to declare your value too large (e.g. long)
|
|
||||||
* <fijal> that way you'll never pass garbage
|
|
||||||
*/
|
|
||||||
typedef intptr_t time_t;
|
|
||||||
|
|
||||||
typedef int ASN1_BOOLEAN;
|
|
||||||
typedef ... ASN1_INTEGER;
|
|
||||||
|
|
||||||
struct asn1_string_st {
|
|
||||||
int length;
|
|
||||||
int type;
|
|
||||||
unsigned char *data;
|
|
||||||
long flags;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct asn1_string_st ASN1_OCTET_STRING;
|
|
||||||
typedef struct asn1_string_st ASN1_IA5STRING;
|
|
||||||
typedef ... ASN1_OBJECT;
|
|
||||||
typedef ... ASN1_STRING;
|
|
||||||
typedef ... ASN1_TYPE;
|
|
||||||
typedef ... ASN1_GENERALIZEDTIME;
|
|
||||||
typedef ... ASN1_ENUMERATED;
|
|
||||||
typedef ... ASN1_ITEM;
|
|
||||||
typedef ... ASN1_VALUE;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
...;
|
|
||||||
} ASN1_TIME;
|
|
||||||
typedef ... ASN1_ITEM_EXP;
|
|
||||||
|
|
||||||
typedef ... ASN1_UTCTIME;
|
|
||||||
|
|
||||||
static const int V_ASN1_GENERALIZEDTIME;
|
|
||||||
|
|
||||||
static const int MBSTRING_UTF8;
|
|
||||||
"""
|
|
||||||
|
|
||||||
FUNCTIONS = """
|
|
||||||
ASN1_OBJECT *ASN1_OBJECT_new(void);
|
|
||||||
void ASN1_OBJECT_free(ASN1_OBJECT *);
|
|
||||||
|
|
||||||
/* ASN1 OBJECT IDENTIFIER */
|
|
||||||
ASN1_OBJECT *d2i_ASN1_OBJECT(ASN1_OBJECT **, const unsigned char **, long);
|
|
||||||
int i2d_ASN1_OBJECT(ASN1_OBJECT *, unsigned char **);
|
|
||||||
|
|
||||||
/* ASN1 STRING */
|
|
||||||
ASN1_STRING *ASN1_STRING_new(void);
|
|
||||||
ASN1_STRING *ASN1_STRING_type_new(int);
|
|
||||||
void ASN1_STRING_free(ASN1_STRING *);
|
|
||||||
unsigned char *ASN1_STRING_data(ASN1_STRING *);
|
|
||||||
int ASN1_STRING_set(ASN1_STRING *, const void *, int);
|
|
||||||
int ASN1_STRING_type(ASN1_STRING *);
|
|
||||||
int ASN1_STRING_to_UTF8(unsigned char **, ASN1_STRING *);
|
|
||||||
|
|
||||||
/* ASN1 OCTET STRING */
|
|
||||||
ASN1_OCTET_STRING *ASN1_OCTET_STRING_new(void);
|
|
||||||
void ASN1_OCTET_STRING_free(ASN1_OCTET_STRING *);
|
|
||||||
int ASN1_OCTET_STRING_set(ASN1_OCTET_STRING *, const unsigned char *, int);
|
|
||||||
|
|
||||||
/* ASN1 INTEGER */
|
|
||||||
ASN1_INTEGER *ASN1_INTEGER_new(void);
|
|
||||||
void ASN1_INTEGER_free(ASN1_INTEGER *);
|
|
||||||
int ASN1_INTEGER_set(ASN1_INTEGER *, long);
|
|
||||||
int i2a_ASN1_INTEGER(BIO *, ASN1_INTEGER *);
|
|
||||||
|
|
||||||
/* ASN1 TIME */
|
|
||||||
ASN1_TIME *ASN1_TIME_new(void);
|
|
||||||
void ASN1_TIME_free(ASN1_TIME *);
|
|
||||||
ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *,
|
|
||||||
ASN1_GENERALIZEDTIME **);
|
|
||||||
|
|
||||||
/* ASN1 UTCTIME */
|
|
||||||
int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *, time_t);
|
|
||||||
|
|
||||||
/* ASN1 GENERALIZEDTIME */
|
|
||||||
int ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *, const char *);
|
|
||||||
void ASN1_GENERALIZEDTIME_free(ASN1_GENERALIZEDTIME *);
|
|
||||||
|
|
||||||
/* ASN1 ENUMERATED */
|
|
||||||
ASN1_ENUMERATED *ASN1_ENUMERATED_new(void);
|
|
||||||
void ASN1_ENUMERATED_free(ASN1_ENUMERATED *);
|
|
||||||
int ASN1_ENUMERATED_set(ASN1_ENUMERATED *, long);
|
|
||||||
|
|
||||||
ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **, const unsigned char **, long,
|
|
||||||
const ASN1_ITEM *);
|
|
||||||
"""
|
|
||||||
|
|
||||||
MACROS = """
|
|
||||||
ASN1_TIME *M_ASN1_TIME_dup(void *);
|
|
||||||
const ASN1_ITEM *ASN1_ITEM_ptr(ASN1_ITEM_EXP *);
|
|
||||||
|
|
||||||
/* These aren't macros these arguments are all const X on openssl > 1.0.x */
|
|
||||||
|
|
||||||
int ASN1_STRING_length(ASN1_STRING *);
|
|
||||||
ASN1_STRING *ASN1_STRING_dup(ASN1_STRING *);
|
|
||||||
int ASN1_STRING_cmp(ASN1_STRING *, ASN1_STRING *);
|
|
||||||
|
|
||||||
ASN1_OCTET_STRING *ASN1_OCTET_STRING_dup(ASN1_OCTET_STRING *);
|
|
||||||
int ASN1_OCTET_STRING_cmp(ASN1_OCTET_STRING *, ASN1_OCTET_STRING *);
|
|
||||||
|
|
||||||
ASN1_INTEGER *ASN1_INTEGER_dup(ASN1_INTEGER *);
|
|
||||||
int ASN1_INTEGER_cmp(ASN1_INTEGER *, ASN1_INTEGER *);
|
|
||||||
long ASN1_INTEGER_get(ASN1_INTEGER *);
|
|
||||||
|
|
||||||
BIGNUM *ASN1_INTEGER_to_BN(ASN1_INTEGER *, BIGNUM *);
|
|
||||||
ASN1_INTEGER *BN_to_ASN1_INTEGER(BIGNUM *, ASN1_INTEGER *);
|
|
||||||
|
|
||||||
/* These isn't a macro the arg is const on openssl 1.0.2+ */
|
|
||||||
int ASN1_GENERALIZEDTIME_check(ASN1_GENERALIZEDTIME *);
|
|
||||||
|
|
||||||
/* Not a macro, const on openssl 1.0 */
|
|
||||||
int ASN1_STRING_set_default_mask_asc(char *);
|
|
||||||
"""
|
|
||||||
|
|
||||||
CUSTOMIZATIONS = """
|
|
||||||
"""
|
|
||||||
|
|
||||||
CONDITIONAL_NAMES = {}
|
|
|
@ -1,114 +0,0 @@
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
# you may not use this file except in compliance with the License.
|
|
||||||
# You may obtain a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
# implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
|
||||||
|
|
||||||
INCLUDES = """
|
|
||||||
#include <openssl/bn.h>
|
|
||||||
"""
|
|
||||||
|
|
||||||
TYPES = """
|
|
||||||
typedef ... BN_CTX;
|
|
||||||
typedef ... BIGNUM;
|
|
||||||
/*
|
|
||||||
* TODO: This typedef is wrong.
|
|
||||||
*
|
|
||||||
* This is due to limitations of cffi.
|
|
||||||
* See https://bitbucket.org/cffi/cffi/issue/69
|
|
||||||
*
|
|
||||||
* For another possible work-around (not used here because it involves more
|
|
||||||
* complicated use of the cffi API which falls outside the general pattern used
|
|
||||||
* by this package), see
|
|
||||||
* http://paste.pound-python.org/show/iJcTUMkKeBeS6yXpZWUU/
|
|
||||||
*
|
|
||||||
* The work-around used here is to just be sure to declare a type that is at
|
|
||||||
* least as large as the real type. Maciej explains:
|
|
||||||
*
|
|
||||||
* <fijal> I think you want to declare your value too large (e.g. long)
|
|
||||||
* <fijal> that way you'll never pass garbage
|
|
||||||
*/
|
|
||||||
typedef uintptr_t BN_ULONG;
|
|
||||||
"""
|
|
||||||
|
|
||||||
FUNCTIONS = """
|
|
||||||
BIGNUM *BN_new(void);
|
|
||||||
void BN_free(BIGNUM *);
|
|
||||||
|
|
||||||
BN_CTX *BN_CTX_new(void);
|
|
||||||
void BN_CTX_free(BN_CTX *);
|
|
||||||
|
|
||||||
void BN_CTX_start(BN_CTX *);
|
|
||||||
BIGNUM *BN_CTX_get(BN_CTX *);
|
|
||||||
void BN_CTX_end(BN_CTX *);
|
|
||||||
|
|
||||||
BIGNUM *BN_copy(BIGNUM *, const BIGNUM *);
|
|
||||||
BIGNUM *BN_dup(const BIGNUM *);
|
|
||||||
|
|
||||||
int BN_set_word(BIGNUM *, BN_ULONG);
|
|
||||||
BN_ULONG BN_get_word(const BIGNUM *);
|
|
||||||
|
|
||||||
const BIGNUM *BN_value_one(void);
|
|
||||||
|
|
||||||
char *BN_bn2hex(const BIGNUM *);
|
|
||||||
int BN_hex2bn(BIGNUM **, const char *);
|
|
||||||
int BN_dec2bn(BIGNUM **, const char *);
|
|
||||||
|
|
||||||
int BN_bn2bin(const BIGNUM *, unsigned char *);
|
|
||||||
BIGNUM *BN_bin2bn(const unsigned char *, int, BIGNUM *);
|
|
||||||
|
|
||||||
int BN_num_bits(const BIGNUM *);
|
|
||||||
|
|
||||||
int BN_cmp(const BIGNUM *, const BIGNUM *);
|
|
||||||
int BN_add(BIGNUM *, const BIGNUM *, const BIGNUM *);
|
|
||||||
int BN_sub(BIGNUM *, const BIGNUM *, const BIGNUM *);
|
|
||||||
int BN_mul(BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
|
|
||||||
int BN_sqr(BIGNUM *, const BIGNUM *, BN_CTX *);
|
|
||||||
int BN_div(BIGNUM *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
|
|
||||||
int BN_nnmod(BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
|
|
||||||
int BN_mod_add(BIGNUM *, const BIGNUM *, const BIGNUM *, const BIGNUM *,
|
|
||||||
BN_CTX *);
|
|
||||||
int BN_mod_sub(BIGNUM *, const BIGNUM *, const BIGNUM *, const BIGNUM *,
|
|
||||||
BN_CTX *);
|
|
||||||
int BN_mod_mul(BIGNUM *, const BIGNUM *, const BIGNUM *, const BIGNUM *,
|
|
||||||
BN_CTX *);
|
|
||||||
int BN_mod_sqr(BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
|
|
||||||
int BN_exp(BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
|
|
||||||
int BN_mod_exp(BIGNUM *, const BIGNUM *, const BIGNUM *, const BIGNUM *,
|
|
||||||
BN_CTX *);
|
|
||||||
int BN_gcd(BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
|
|
||||||
BIGNUM *BN_mod_inverse(BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
|
|
||||||
|
|
||||||
int BN_set_bit(BIGNUM *, int);
|
|
||||||
int BN_clear_bit(BIGNUM *, int);
|
|
||||||
|
|
||||||
int BN_is_bit_set(const BIGNUM *, int);
|
|
||||||
|
|
||||||
int BN_mask_bits(BIGNUM *, int);
|
|
||||||
"""
|
|
||||||
|
|
||||||
MACROS = """
|
|
||||||
int BN_zero(BIGNUM *);
|
|
||||||
int BN_one(BIGNUM *);
|
|
||||||
int BN_mod(BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
|
|
||||||
|
|
||||||
int BN_lshift(BIGNUM *, const BIGNUM *, int);
|
|
||||||
int BN_lshift1(BIGNUM *, BIGNUM *);
|
|
||||||
|
|
||||||
int BN_rshift(BIGNUM *, BIGNUM *, int);
|
|
||||||
int BN_rshift1(BIGNUM *, BIGNUM *);
|
|
||||||
"""
|
|
||||||
|
|
||||||
CUSTOMIZATIONS = """
|
|
||||||
"""
|
|
||||||
|
|
||||||
CONDITIONAL_NAMES = {}
|
|
|
@ -1,119 +1,137 @@
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# This file is dual licensed under the terms of the Apache License, Version
|
||||||
# you may not use this file except in compliance with the License.
|
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
|
||||||
# You may obtain a copy of the License at
|
# for complete details.
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
# implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
|
import collections
|
||||||
import os
|
import os
|
||||||
import sys
|
|
||||||
import threading
|
import threading
|
||||||
|
import types
|
||||||
|
|
||||||
from cryptography.hazmat.bindings.utils import build_ffi
|
from cryptography.exceptions import InternalError
|
||||||
|
from cryptography.hazmat.bindings._openssl import ffi, lib
|
||||||
|
from cryptography.hazmat.bindings.openssl._conditional import CONDITIONAL_NAMES
|
||||||
|
|
||||||
|
|
||||||
_OSX_PRE_INCLUDE = """
|
_OpenSSLError = collections.namedtuple("_OpenSSLError",
|
||||||
#ifdef __APPLE__
|
["code", "lib", "func", "reason"])
|
||||||
#include <AvailabilityMacros.h>
|
|
||||||
#define __ORIG_DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER \
|
|
||||||
DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
|
|
||||||
#undef DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
|
|
||||||
#define DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
|
|
||||||
#endif
|
|
||||||
"""
|
|
||||||
|
|
||||||
_OSX_POST_INCLUDE = """
|
|
||||||
#ifdef __APPLE__
|
def _consume_errors(lib):
|
||||||
#undef DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
|
errors = []
|
||||||
#define DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER \
|
while True:
|
||||||
__ORIG_DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
|
code = lib.ERR_get_error()
|
||||||
#endif
|
if code == 0:
|
||||||
"""
|
break
|
||||||
|
|
||||||
|
err_lib = lib.ERR_GET_LIB(code)
|
||||||
|
err_func = lib.ERR_GET_FUNC(code)
|
||||||
|
err_reason = lib.ERR_GET_REASON(code)
|
||||||
|
|
||||||
|
errors.append(_OpenSSLError(code, err_lib, err_func, err_reason))
|
||||||
|
return errors
|
||||||
|
|
||||||
|
|
||||||
|
def _openssl_assert(lib, ok):
|
||||||
|
if not ok:
|
||||||
|
errors = _consume_errors(lib)
|
||||||
|
raise InternalError(
|
||||||
|
"Unknown OpenSSL error. Please file an issue at https://github.com"
|
||||||
|
"/pyca/cryptography/issues with information on how to reproduce "
|
||||||
|
"this.",
|
||||||
|
errors
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ffi.callback("int (*)(unsigned char *, int)", error=-1)
|
||||||
|
def _osrandom_rand_bytes(buf, size):
|
||||||
|
signed = ffi.cast("char *", buf)
|
||||||
|
result = os.urandom(size)
|
||||||
|
signed[0:size] = result
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
@ffi.callback("int (*)(void)")
|
||||||
|
def _osrandom_rand_status():
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
def build_conditional_library(lib, conditional_names):
|
||||||
|
conditional_lib = types.ModuleType("lib")
|
||||||
|
excluded_names = set()
|
||||||
|
for condition, names in conditional_names.items():
|
||||||
|
if not getattr(lib, condition):
|
||||||
|
excluded_names |= set(names)
|
||||||
|
|
||||||
|
for attr in dir(lib):
|
||||||
|
if attr not in excluded_names:
|
||||||
|
setattr(conditional_lib, attr, getattr(lib, attr))
|
||||||
|
|
||||||
|
return conditional_lib
|
||||||
|
|
||||||
|
|
||||||
class Binding(object):
|
class Binding(object):
|
||||||
"""
|
"""
|
||||||
OpenSSL API wrapper.
|
OpenSSL API wrapper.
|
||||||
"""
|
"""
|
||||||
_module_prefix = "cryptography.hazmat.bindings.openssl."
|
lib = None
|
||||||
_modules = [
|
ffi = ffi
|
||||||
"aes",
|
_lib_loaded = False
|
||||||
"asn1",
|
|
||||||
"bignum",
|
|
||||||
"bio",
|
|
||||||
"cmac",
|
|
||||||
"cms",
|
|
||||||
"conf",
|
|
||||||
"crypto",
|
|
||||||
"dh",
|
|
||||||
"dsa",
|
|
||||||
"ec",
|
|
||||||
"ecdh",
|
|
||||||
"ecdsa",
|
|
||||||
"engine",
|
|
||||||
"err",
|
|
||||||
"evp",
|
|
||||||
"hmac",
|
|
||||||
"nid",
|
|
||||||
"objects",
|
|
||||||
"opensslv",
|
|
||||||
"osrandom_engine",
|
|
||||||
"pem",
|
|
||||||
"pkcs7",
|
|
||||||
"pkcs12",
|
|
||||||
"rand",
|
|
||||||
"rsa",
|
|
||||||
"ssl",
|
|
||||||
"x509",
|
|
||||||
"x509name",
|
|
||||||
"x509v3",
|
|
||||||
"x509_vfy"
|
|
||||||
]
|
|
||||||
|
|
||||||
_locks = None
|
_locks = None
|
||||||
_lock_cb_handle = None
|
_lock_cb_handle = None
|
||||||
|
_init_lock = threading.Lock()
|
||||||
_lock_init_lock = threading.Lock()
|
_lock_init_lock = threading.Lock()
|
||||||
|
|
||||||
ffi = None
|
_osrandom_engine_id = ffi.new("const char[]", b"osrandom")
|
||||||
lib = None
|
_osrandom_engine_name = ffi.new("const char[]", b"osrandom_engine")
|
||||||
|
_osrandom_method = ffi.new(
|
||||||
|
"RAND_METHOD *",
|
||||||
|
dict(bytes=_osrandom_rand_bytes, pseudorand=_osrandom_rand_bytes,
|
||||||
|
status=_osrandom_rand_status)
|
||||||
|
)
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._ensure_ffi_initialized()
|
self._ensure_ffi_initialized()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _ensure_ffi_initialized(cls):
|
def _register_osrandom_engine(cls):
|
||||||
if cls.ffi is not None and cls.lib is not None:
|
_openssl_assert(cls.lib, cls.lib.ERR_peek_error() == 0)
|
||||||
return
|
|
||||||
|
|
||||||
# OpenSSL goes by a different library name on different operating
|
engine = cls.lib.ENGINE_new()
|
||||||
# systems.
|
_openssl_assert(cls.lib, engine != cls.ffi.NULL)
|
||||||
if sys.platform != "win32":
|
try:
|
||||||
# In some circumstances, the order in which these libs are
|
result = cls.lib.ENGINE_set_id(engine, cls._osrandom_engine_id)
|
||||||
# specified on the linker command-line is significant;
|
_openssl_assert(cls.lib, result == 1)
|
||||||
# libssl must come before libcrypto
|
result = cls.lib.ENGINE_set_name(engine, cls._osrandom_engine_name)
|
||||||
# (http://marc.info/?l=openssl-users&m=135361825921871)
|
_openssl_assert(cls.lib, result == 1)
|
||||||
libraries = ["ssl", "crypto"]
|
result = cls.lib.ENGINE_set_RAND(engine, cls._osrandom_method)
|
||||||
else: # pragma: no cover
|
_openssl_assert(cls.lib, result == 1)
|
||||||
link_type = os.environ.get("PYCA_WINDOWS_LINK_TYPE", "static")
|
result = cls.lib.ENGINE_add(engine)
|
||||||
libraries = _get_windows_libraries(link_type)
|
if result != 1:
|
||||||
|
errors = _consume_errors(cls.lib)
|
||||||
cls.ffi, cls.lib = build_ffi(
|
_openssl_assert(
|
||||||
module_prefix=cls._module_prefix,
|
cls.lib,
|
||||||
modules=cls._modules,
|
errors[0].reason == cls.lib.ENGINE_R_CONFLICTING_ENGINE_ID
|
||||||
pre_include=_OSX_PRE_INCLUDE,
|
|
||||||
post_include=_OSX_POST_INCLUDE,
|
|
||||||
libraries=libraries,
|
|
||||||
)
|
)
|
||||||
res = cls.lib.Cryptography_add_osrandom_engine()
|
|
||||||
assert res != 0
|
finally:
|
||||||
|
result = cls.lib.ENGINE_free(engine)
|
||||||
|
_openssl_assert(cls.lib, result == 1)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _ensure_ffi_initialized(cls):
|
||||||
|
with cls._init_lock:
|
||||||
|
if not cls._lib_loaded:
|
||||||
|
cls.lib = build_conditional_library(lib, CONDITIONAL_NAMES)
|
||||||
|
cls._lib_loaded = True
|
||||||
|
# initialize the SSL library
|
||||||
|
cls.lib.SSL_library_init()
|
||||||
|
# adds all ciphers/digests for EVP
|
||||||
|
cls.lib.OpenSSL_add_all_algorithms()
|
||||||
|
# loads error strings for libcrypto and libssl functions
|
||||||
|
cls.lib.SSL_load_error_strings()
|
||||||
|
cls._register_osrandom_engine()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def init_static_locks(cls):
|
def init_static_locks(cls):
|
||||||
|
@ -156,13 +174,9 @@ class Binding(object):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def _get_windows_libraries(link_type):
|
# OpenSSL is not thread safe until the locks are initialized. We call this
|
||||||
if link_type == "dynamic":
|
# method in module scope so that it executes with the import lock. On
|
||||||
return ["libeay32", "ssleay32", "advapi32"]
|
# Pythons < 3.4 this import lock is a global lock, which can prevent a race
|
||||||
elif link_type == "static" or link_type == "":
|
# condition registering the OpenSSL locks. On Python 3.4+ the import lock
|
||||||
return ["libeay32mt", "ssleay32mt", "advapi32",
|
# is per module so this approach will not work.
|
||||||
"crypt32", "gdi32", "user32", "ws2_32"]
|
Binding.init_static_locks()
|
||||||
else:
|
|
||||||
raise ValueError(
|
|
||||||
"PYCA_WINDOWS_LINK_TYPE must be 'static' or 'dynamic'"
|
|
||||||
)
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue