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
|
||||
*.pyd
|
||||
__pycache__
|
||||
pip_cache
|
||||
|
|
|
@ -1,29 +1,39 @@
|
|||
from sys import platform
|
||||
from functools import wraps, partial
|
||||
from itertools import count
|
||||
from itertools import count, chain
|
||||
from weakref import WeakValueDictionary
|
||||
from errno import errorcode
|
||||
|
||||
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 int2byte, indexbytes
|
||||
|
||||
from OpenSSL._util import (
|
||||
ffi as _ffi,
|
||||
lib as _lib,
|
||||
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 (
|
||||
FILETYPE_PEM, _PassphraseHelper, PKey, X509Name, X509, X509Store)
|
||||
|
||||
_unspecified = object()
|
||||
|
||||
try:
|
||||
_memoryview = memoryview
|
||||
except NameError:
|
||||
class _memoryview(object):
|
||||
pass
|
||||
|
||||
try:
|
||||
_buffer = buffer
|
||||
except NameError:
|
||||
class _buffer(object):
|
||||
pass
|
||||
|
||||
OPENSSL_VERSION_NUMBER = _lib.OPENSSL_VERSION_NUMBER
|
||||
SSLEAY_VERSION = _lib.SSLEAY_VERSION
|
||||
SSLEAY_CFLAGS = _lib.SSLEAY_CFLAGS
|
||||
|
@ -81,7 +91,10 @@ except AttributeError:
|
|||
|
||||
OP_NO_QUERY_MTU = _lib.SSL_OP_NO_QUERY_MTU
|
||||
OP_COOKIE_EXCHANGE = _lib.SSL_OP_COOKIE_EXCHANGE
|
||||
try:
|
||||
OP_NO_TICKET = _lib.SSL_OP_NO_TICKET
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
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_DONE = _lib.SSL_CB_HANDSHAKE_DONE
|
||||
|
||||
|
||||
class Error(Exception):
|
||||
"""
|
||||
An error occurred in an `OpenSSL.SSL` API.
|
||||
|
@ -156,11 +168,42 @@ class SysCallError(Error):
|
|||
pass
|
||||
|
||||
|
||||
class _CallbackExceptionHelper(object):
|
||||
"""
|
||||
A base class for wrapper classes that allow for intelligent exception
|
||||
handling in OpenSSL callbacks.
|
||||
|
||||
class _VerifyHelper(object):
|
||||
def __init__(self, connection, callback):
|
||||
:ivar list _problems: Any exceptions that occurred while executing in a
|
||||
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 = []
|
||||
|
||||
|
||||
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)
|
||||
def wrapper(ok, store_ctx):
|
||||
cert = X509.__new__(X509)
|
||||
|
@ -168,6 +211,10 @@ class _VerifyHelper(object):
|
|||
error_number = _lib.X509_STORE_CTX_get_error(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:
|
||||
result = callback(connection, cert, error_number, error_depth, ok)
|
||||
except Exception as e:
|
||||
|
@ -184,14 +231,142 @@ class _VerifyHelper(object):
|
|||
"int (*)(int, X509_STORE_CTX *)", wrapper)
|
||||
|
||||
|
||||
def raise_if_problem(self):
|
||||
if self._problems:
|
||||
try:
|
||||
_raise_current_error()
|
||||
except Error:
|
||||
pass
|
||||
raise self._problems.pop(0)
|
||||
class _NpnAdvertiseHelper(_CallbackExceptionHelper):
|
||||
"""
|
||||
Wrap a callback such that it can be used as an NPN advertisement callback.
|
||||
"""
|
||||
def __init__(self, callback):
|
||||
_CallbackExceptionHelper.__init__(self)
|
||||
|
||||
@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):
|
||||
|
@ -223,6 +398,37 @@ def 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):
|
||||
pass
|
||||
|
@ -235,6 +441,7 @@ class Context(object):
|
|||
new SSL connections.
|
||||
"""
|
||||
_methods = {
|
||||
SSLv2_METHOD: "SSLv2_method",
|
||||
SSLv3_METHOD: "SSLv3_method",
|
||||
SSLv23_METHOD: "SSLv23_method",
|
||||
TLSv1_METHOD: "TLSv1_method",
|
||||
|
@ -280,6 +487,12 @@ class Context(object):
|
|||
self._info_callback = None
|
||||
self._tlsext_servername_callback = 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_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
|
||||
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
|
||||
(``bytes`` or ``unicode``).
|
||||
|
||||
:return: None
|
||||
"""
|
||||
if cafile is None:
|
||||
cafile = _ffi.NULL
|
||||
elif not isinstance(cafile, bytes):
|
||||
raise TypeError("cafile must be None or a byte string")
|
||||
else:
|
||||
cafile = _path_string(cafile)
|
||||
|
||||
if capath is None:
|
||||
capath = _ffi.NULL
|
||||
elif not isinstance(capath, bytes):
|
||||
raise TypeError("capath must be None or a byte string")
|
||||
else:
|
||||
capath = _path_string(capath)
|
||||
|
||||
load_result = _lib.SSL_CTX_load_verify_locations(self._context, cafile, capath)
|
||||
if not load_result:
|
||||
|
@ -355,15 +571,12 @@ class Context(object):
|
|||
"""
|
||||
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
|
||||
"""
|
||||
if isinstance(certfile, _text_type):
|
||||
# Perhaps sys.getfilesystemencoding() could be better?
|
||||
certfile = certfile.encode("utf-8")
|
||||
|
||||
if not isinstance(certfile, bytes):
|
||||
raise TypeError("certfile must be bytes or unicode")
|
||||
certfile = _path_string(certfile)
|
||||
|
||||
result = _lib.SSL_CTX_use_certificate_chain_file(self._context, certfile)
|
||||
if not result:
|
||||
|
@ -374,15 +587,13 @@ class Context(object):
|
|||
"""
|
||||
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
|
||||
|
||||
:return: None
|
||||
"""
|
||||
if isinstance(certfile, _text_type):
|
||||
# Perhaps sys.getfilesystemencoding() could be better?
|
||||
certfile = certfile.encode("utf-8")
|
||||
if not isinstance(certfile, bytes):
|
||||
raise TypeError("certfile must be bytes or unicode")
|
||||
certfile = _path_string(certfile)
|
||||
if not isinstance(filetype, integer_types):
|
||||
raise TypeError("filetype must be an integer")
|
||||
|
||||
|
@ -432,22 +643,18 @@ class Context(object):
|
|||
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
|
||||
|
||||
: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
|
||||
|
||||
:return: None
|
||||
"""
|
||||
if isinstance(keyfile, _text_type):
|
||||
# Perhaps sys.getfilesystemencoding() could be better?
|
||||
keyfile = keyfile.encode("utf-8")
|
||||
keyfile = _path_string(keyfile)
|
||||
|
||||
if not isinstance(keyfile, bytes):
|
||||
raise TypeError("keyfile must be a byte string")
|
||||
|
||||
if filetype is _unspecified:
|
||||
if filetype is _UNSPECIFIED:
|
||||
filetype = FILETYPE_PEM
|
||||
elif not isinstance(filetype, integer_types):
|
||||
raise TypeError("filetype must be an integer")
|
||||
|
@ -479,6 +686,9 @@ class Context(object):
|
|||
|
||||
: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):
|
||||
"""
|
||||
|
@ -538,7 +748,7 @@ class Context(object):
|
|||
if not callable(callback):
|
||||
raise TypeError("callback must be callable")
|
||||
|
||||
self._verify_helper = _VerifyHelper(self, callback)
|
||||
self._verify_helper = _VerifyHelper(callback)
|
||||
self._verify_callback = self._verify_helper.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
|
||||
|
||||
:param dhfile: The file to load EDH parameters from
|
||||
:param dhfile: The file to load EDH parameters from (``bytes`` or
|
||||
``unicode``).
|
||||
|
||||
:return: None
|
||||
"""
|
||||
if not isinstance(dhfile, bytes):
|
||||
raise TypeError("dhfile must be a byte string")
|
||||
dhfile = _path_string(dhfile)
|
||||
|
||||
bio = _lib.BIO_new_file(dhfile, b"r")
|
||||
if bio == _ffi.NULL:
|
||||
|
@ -594,6 +805,19 @@ class Context(object):
|
|||
_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):
|
||||
"""
|
||||
Change the cipher list
|
||||
|
@ -783,6 +1007,79 @@ class Context(object):
|
|||
_lib.SSL_CTX_set_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
|
||||
|
||||
|
||||
|
@ -807,6 +1104,19 @@ class Connection(object):
|
|||
self._ssl = _ffi.gc(ssl, _lib.SSL_free)
|
||||
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
|
||||
|
||||
if socket is None:
|
||||
|
@ -841,6 +1151,12 @@ class Connection(object):
|
|||
def _raise_ssl_error(self, ssl, result):
|
||||
if self._context._verify_helper is not None:
|
||||
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)
|
||||
if error == _lib.SSL_ERROR_WANT_READ:
|
||||
|
@ -859,7 +1175,7 @@ class Connection(object):
|
|||
errno = _ffi.getwinerror()[0]
|
||||
else:
|
||||
errno = _ffi.errno
|
||||
raise SysCallError(errno, errorcode[errno])
|
||||
raise SysCallError(errno, errorcode.get(errno))
|
||||
else:
|
||||
raise SysCallError(-1, "Unexpected EOF")
|
||||
else:
|
||||
|
@ -936,15 +1252,20 @@ class Connection(object):
|
|||
WantWrite or WantX509Lookup exceptions on this, you have to call the
|
||||
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
|
||||
API, the value is ignored
|
||||
:return: The number of bytes written
|
||||
"""
|
||||
# Backward compatibility
|
||||
buf = _text_to_bytes_and_warn("buf", buf)
|
||||
|
||||
if isinstance(buf, _memoryview):
|
||||
buf = buf.tobytes()
|
||||
if isinstance(buf, _buffer):
|
||||
buf = str(buf)
|
||||
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))
|
||||
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
|
||||
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
|
||||
API, the value is ignored
|
||||
:return: The number of bytes written
|
||||
"""
|
||||
buf = _text_to_bytes_and_warn("buf", buf)
|
||||
|
||||
if isinstance(buf, _memoryview):
|
||||
buf = buf.tobytes()
|
||||
if isinstance(buf, _buffer):
|
||||
buf = str(buf)
|
||||
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)
|
||||
total_sent = 0
|
||||
|
@ -997,6 +1322,45 @@ class Connection(object):
|
|||
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):
|
||||
if _lib.BIO_should_retry(bio):
|
||||
if _lib.BIO_should_read(bio):
|
||||
|
@ -1046,6 +1410,8 @@ class Connection(object):
|
|||
:param buf: The string to put into the memory BIO.
|
||||
:return: The number of bytes written
|
||||
"""
|
||||
buf = _text_to_bytes_and_warn("buf", buf)
|
||||
|
||||
if self._into_ssl is None:
|
||||
raise TypeError("Connection sock was not None")
|
||||
|
||||
|
@ -1153,8 +1519,7 @@ class Connection(object):
|
|||
"""
|
||||
result = _lib.SSL_shutdown(self._ssl)
|
||||
if result < 0:
|
||||
# TODO: This is untested.
|
||||
_raise_current_error()
|
||||
self._raise_ssl_error(self._ssl, result)
|
||||
elif result > 0:
|
||||
return True
|
||||
else:
|
||||
|
@ -1210,7 +1575,7 @@ class Connection(object):
|
|||
The makefile() method is not implemented, since there is no dup semantics
|
||||
for SSL connections
|
||||
|
||||
:raise NotImplementedError
|
||||
:raise: NotImplementedError
|
||||
"""
|
||||
raise NotImplementedError("Cannot make file object of OpenSSL.SSL.Connection")
|
||||
|
||||
|
@ -1416,6 +1781,166 @@ class Connection(object):
|
|||
if not result:
|
||||
_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
|
||||
|
||||
# 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 cryptography.hazmat.bindings.openssl.binding import Binding
|
||||
|
@ -5,11 +8,34 @@ binding = Binding()
|
|||
ffi = binding.ffi
|
||||
lib = binding.lib
|
||||
|
||||
def exception_from_error_queue(exceptionType):
|
||||
|
||||
|
||||
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))
|
||||
|
||||
|
||||
|
||||
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 = []
|
||||
|
||||
while True:
|
||||
error = lib.ERR_get_error()
|
||||
if error == 0:
|
||||
|
@ -19,7 +45,7 @@ def exception_from_error_queue(exceptionType):
|
|||
text(lib.ERR_func_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:
|
||||
def byte_string(s):
|
||||
return s.encode("charmap")
|
||||
else:
|
||||
def byte_string(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 functools import partial
|
||||
from operator import __eq__, __ne__, __lt__, __le__, __gt__, __ge__
|
||||
from warnings import warn as _warn
|
||||
|
||||
from six import (
|
||||
integer_types as _integer_types,
|
||||
text_type as _text_type)
|
||||
text_type as _text_type,
|
||||
PY3 as _PY3)
|
||||
|
||||
from OpenSSL._util import (
|
||||
ffi as _ffi,
|
||||
lib as _lib,
|
||||
exception_from_error_queue as _exception_from_error_queue,
|
||||
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_ASN1 = _lib.SSL_FILETYPE_ASN1
|
||||
|
@ -24,6 +29,7 @@ TYPE_RSA = _lib.EVP_PKEY_RSA
|
|||
TYPE_DSA = _lib.EVP_PKEY_DSA
|
||||
|
||||
|
||||
|
||||
class Error(Exception):
|
||||
"""
|
||||
An error occurred in an `OpenSSL.crypto` API.
|
||||
|
@ -32,6 +38,8 @@ class Error(Exception):
|
|||
|
||||
_raise_current_error = partial(_exception_from_error_queue, Error)
|
||||
|
||||
|
||||
|
||||
def _untested_error(where):
|
||||
"""
|
||||
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):
|
||||
def __init__(self, name):
|
||||
"""
|
||||
|
@ -697,6 +855,21 @@ class X509Req(object):
|
|||
_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):
|
||||
"""
|
||||
Sign the certificate request using the supplied key and digest
|
||||
|
@ -1190,6 +1363,125 @@ class X509Store(object):
|
|||
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):
|
||||
"""
|
||||
|
@ -1308,9 +1600,11 @@ def _X509_REVOKED_dup(original):
|
|||
_raise_current_error()
|
||||
|
||||
if original.serialNumber != _ffi.NULL:
|
||||
_lib.ASN1_INTEGER_free(copy.serialNumber)
|
||||
copy.serialNumber = _lib.ASN1_INTEGER_dup(original.serialNumber)
|
||||
|
||||
if original.revocationDate != _ffi.NULL:
|
||||
_lib.ASN1_TIME_free(copy.revocationDate)
|
||||
copy.revocationDate = _lib.M_ASN1_TIME_dup(original.revocationDate)
|
||||
|
||||
if original.extensions != _ffi.NULL:
|
||||
|
@ -1539,7 +1833,8 @@ class CRL(object):
|
|||
_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
|
||||
|
||||
|
@ -1549,12 +1844,15 @@ class CRL(object):
|
|||
:param key: Used to sign CRL.
|
||||
: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.
|
||||
:type days: :py:data:`int`
|
||||
:param int days: The number of days until the next update of this CRL.
|
||||
|
||||
: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):
|
||||
raise TypeError("cert must be an X509 instance")
|
||||
|
@ -1563,6 +1861,19 @@ class CRL(object):
|
|||
if not isinstance(type, int):
|
||||
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())
|
||||
if bio == _ffi.NULL:
|
||||
# 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))
|
||||
|
||||
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:
|
||||
_raise_current_error()
|
||||
|
||||
|
@ -1729,7 +2040,7 @@ class PKCS12(object):
|
|||
|
||||
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.
|
||||
: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
|
||||
"""
|
||||
passphrase = _text_to_bytes_and_warn("passphrase", passphrase)
|
||||
|
||||
if self._cacerts is None:
|
||||
cacerts = _ffi.NULL
|
||||
else:
|
||||
|
@ -2081,6 +2394,8 @@ def sign(pkey, data, digest):
|
|||
:param digest: message digest to use
|
||||
:return: signature
|
||||
"""
|
||||
data = _text_to_bytes_and_warn("data", data)
|
||||
|
||||
digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
|
||||
if digest_obj == _ffi.NULL:
|
||||
raise ValueError("No such digest method")
|
||||
|
@ -2115,6 +2430,8 @@ def verify(cert, signature, data, digest):
|
|||
:param digest: message digest to use
|
||||
: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))
|
||||
if digest_obj == _ffi.NULL:
|
||||
raise ValueError("No such digest method")
|
||||
|
@ -2136,7 +2453,6 @@ def verify(cert, signature, data, digest):
|
|||
_raise_current_error()
|
||||
|
||||
|
||||
|
||||
def load_crl(type, buffer):
|
||||
"""
|
||||
Load a certificate revocation list from a buffer
|
||||
|
@ -2183,7 +2499,7 @@ def load_pkcs7_data(type, buffer):
|
|||
if type == FILETYPE_PEM:
|
||||
pkcs7 = _lib.PEM_read_bio_PKCS7(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
|
||||
elif type == FILETYPE_ASN1:
|
||||
pass
|
||||
pkcs7 = _lib.d2i_PKCS7_bio(bio, _ffi.NULL)
|
||||
else:
|
||||
# TODO: This is untested.
|
||||
_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
|
||||
|
||||
|
@ -2206,11 +2522,20 @@ def load_pkcs12(buffer, passphrase):
|
|||
:param passphrase: (Optional) The password to decrypt the PKCS12 lump
|
||||
:returns: The PKCS12 object
|
||||
"""
|
||||
passphrase = _text_to_bytes_and_warn("passphrase", passphrase)
|
||||
|
||||
if isinstance(buffer, _text_type):
|
||||
buffer = buffer.encode("ascii")
|
||||
|
||||
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)
|
||||
if p12 == _ffi.NULL:
|
||||
_raise_current_error()
|
||||
|
|
|
@ -11,7 +11,8 @@ from six import integer_types as _integer_types
|
|||
from OpenSSL._util import (
|
||||
ffi as _ffi,
|
||||
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):
|
||||
|
@ -131,13 +132,13 @@ def load_file(filename, maxbytes=_unspecified):
|
|||
"""
|
||||
Seed the PRNG with data from a file
|
||||
|
||||
:param filename: The file to read data from
|
||||
:param maxbytes: (optional) The number of bytes to read, default is
|
||||
to read the entire file
|
||||
:param filename: The file to read data from (``bytes`` or ``unicode``).
|
||||
:param maxbytes: (optional) The number of bytes to read, default is to read
|
||||
the entire file
|
||||
|
||||
:return: The number of bytes read
|
||||
"""
|
||||
if not isinstance(filename, _builtin_bytes):
|
||||
raise TypeError("filename must be a string")
|
||||
filename = _path_string(filename)
|
||||
|
||||
if maxbytes is _unspecified:
|
||||
maxbytes = -1
|
||||
|
@ -152,12 +153,11 @@ def write_file(filename):
|
|||
"""
|
||||
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
|
||||
"""
|
||||
if not isinstance(filename, _builtin_bytes):
|
||||
raise TypeError("filename must be a string")
|
||||
|
||||
filename = _path_string(filename)
|
||||
return _lib.RAND_write_file(filename)
|
||||
|
||||
|
||||
|
|
|
@ -6,16 +6,22 @@ Unit tests for :py:mod:`OpenSSL.crypto`.
|
|||
"""
|
||||
|
||||
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 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 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 load_certificate, load_privatekey
|
||||
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 CRL, Revoked, load_crl
|
||||
from OpenSSL.crypto import NetscapeSPKI, NetscapeSPKIType
|
||||
from OpenSSL.crypto import sign, verify
|
||||
from OpenSSL.test.util import TestCase, b
|
||||
from OpenSSL._util import native
|
||||
from OpenSSL.crypto import (
|
||||
sign, verify, get_elliptic_curve, get_elliptic_curves)
|
||||
from OpenSSL.test.util import (
|
||||
EqualityTestsMixin, TestCase, WARNING_TYPE_EXPECTED
|
||||
)
|
||||
from OpenSSL._util import native, lib
|
||||
|
||||
def normalize_certificate_pem(pem):
|
||||
return dump_certificate(FILETYPE_PEM, load_certificate(FILETYPE_PEM, pem))
|
||||
|
@ -80,6 +89,40 @@ cbvAhow217X9V0dVerEOKxnNYspXRrh36h7k4mQA+sDq
|
|||
-----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-----
|
||||
MIICKDCCAZGgAwIBAgIJAJn/HpR21r/8MA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNV
|
||||
BAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UEBxMHQ2hpY2FnbzEQMA4GA1UEChMH
|
||||
|
@ -113,6 +156,40 @@ r50+LF74iLXFwqysVCebPKMOpDWp/qQ1BbJQIPs7/A==
|
|||
-----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-----
|
||||
MIICJjCCAY+gAwIBAgIJAKxpFI5lODkjMA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNV
|
||||
BAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UEBxMHQ2hpY2FnbzEQMA4GA1UEChMH
|
||||
|
@ -247,6 +324,27 @@ Ho4EzbYCOaEAMQA=
|
|||
-----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("""\
|
||||
-----BEGIN X509 CRL-----
|
||||
MIIBWzCBxTANBgkqhkiG9w0BAQQFADBYMQswCQYDVQQGEwJVUzELMAkGA1UECBMC
|
||||
|
@ -512,7 +610,7 @@ class X509ExtTests(TestCase):
|
|||
|
||||
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.
|
||||
"""
|
||||
ext2 = X509Extension(
|
||||
|
@ -1108,7 +1206,32 @@ class X509ReqTests(TestCase, _PKeyInteractionTestsMixin):
|
|||
request = X509Req()
|
||||
request.add_extensions([
|
||||
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):
|
||||
|
@ -1915,6 +2038,21 @@ class PKCS12Tests(TestCase):
|
|||
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):
|
||||
"""
|
||||
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
|
||||
p12_str = _runopenssl(
|
||||
pem, b"pkcs12", b"-export", b"-clcerts", b"-passout", b"pass:" + passwd)
|
||||
p12 = load_pkcs12(p12_str, passwd)
|
||||
# verify
|
||||
self.assertTrue(isinstance(p12, PKCS12))
|
||||
cert_pem = dump_certificate(FILETYPE_PEM, p12.get_certificate())
|
||||
self.assertEqual(cert_pem, client_cert_pem)
|
||||
key_pem = dump_privatekey(FILETYPE_PEM, p12.get_privatekey())
|
||||
self.assertEqual(key_pem, client_key_pem)
|
||||
self.assertEqual(None, p12.get_ca_certificates())
|
||||
p12 = load_pkcs12(p12_str, passphrase=passwd)
|
||||
self.verify_pkcs12_container(p12)
|
||||
|
||||
|
||||
def test_load_pkcs12_text_passphrase(self):
|
||||
"""
|
||||
A PKCS12 string generated using the openssl command line can be loaded
|
||||
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):
|
||||
|
@ -2073,6 +2292,26 @@ class PKCS12Tests(TestCase):
|
|||
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):
|
||||
"""
|
||||
: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)
|
||||
|
||||
|
||||
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:`PKCS7Type`.
|
||||
|
@ -2472,6 +2711,15 @@ class FunctionTests(TestCase):
|
|||
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):
|
||||
"""
|
||||
If the data passed to :py:obj:`load_pkcs7_data` is invalid,
|
||||
|
@ -2796,11 +3044,9 @@ class CRLTests(TestCase):
|
|||
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
|
||||
the CRL in formats of PEM, DER and text. Those outputs are verified
|
||||
with the openssl program.
|
||||
Get a new ``CRL`` with a revocation.
|
||||
"""
|
||||
crl = CRL()
|
||||
revoked = Revoked()
|
||||
|
@ -2809,26 +3055,110 @@ class CRLTests(TestCase):
|
|||
revoked.set_serial(b('3ab'))
|
||||
revoked.set_reason(b('sUpErSeDEd'))
|
||||
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
|
||||
dumped_crl = crl.export(self.cert, self.pkey, days=20)
|
||||
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('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
|
||||
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('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
|
||||
dumped_text = crl.export(self.cert, self.pkey, type=FILETYPE_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):
|
||||
"""
|
||||
If :py:obj:`CRL.export` is used with an uninitialized :py:obj:`X509`
|
||||
|
@ -2859,7 +3189,7 @@ class CRLTests(TestCase):
|
|||
crl = CRL()
|
||||
self.assertRaises(TypeError, crl.export)
|
||||
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, self.cert, None, FILETYPE_PEM, 10)
|
||||
|
@ -2877,6 +3207,19 @@ class CRLTests(TestCase):
|
|||
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):
|
||||
"""
|
||||
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):
|
||||
"""
|
||||
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")
|
||||
|
||||
|
||||
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):
|
||||
"""
|
||||
: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")
|
||||
|
||||
|
||||
|
||||
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__':
|
||||
main()
|
||||
|
|
|
@ -10,7 +10,7 @@ import os
|
|||
import stat
|
||||
import sys
|
||||
|
||||
from OpenSSL.test.util import TestCase, b
|
||||
from OpenSSL.test.util import NON_ASCII, TestCase, b
|
||||
from OpenSSL import rand
|
||||
|
||||
|
||||
|
@ -176,27 +176,47 @@ class RandTests(TestCase):
|
|||
self.assertRaises(TypeError, rand.write_file, 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:
|
||||
rand.write_file(tmpfile)
|
||||
# Write random bytes to a file
|
||||
rand.write_file(path)
|
||||
|
||||
# Verify length of written file
|
||||
size = os.stat(tmpfile)[stat.ST_SIZE]
|
||||
size = os.stat(path)[stat.ST_SIZE]
|
||||
self.assertEqual(1024, size)
|
||||
|
||||
# Read random bytes from file
|
||||
rand.load_file(tmpfile)
|
||||
rand.load_file(tmpfile, 4) # specify a length
|
||||
rand.load_file(path)
|
||||
rand.load_file(path, 4) # specify a length
|
||||
finally:
|
||||
# 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__':
|
||||
|
|
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
|
||||
import sys
|
||||
|
||||
from six import PY3
|
||||
|
||||
from OpenSSL._util import exception_from_error_queue
|
||||
from OpenSSL.crypto import Error
|
||||
|
||||
|
@ -25,6 +27,11 @@ except Exception:
|
|||
|
||||
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):
|
||||
"""
|
||||
:py:class:`TestCase` adds useful testing functionality beyond what is available
|
||||
|
@ -210,7 +217,24 @@ class TestCase(TestCase):
|
|||
return containee
|
||||
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
|
||||
obect-identity-equality test, not an object equality
|
||||
|
@ -222,10 +246,10 @@ class TestCase(TestCase):
|
|||
if first is not second:
|
||||
raise self.failureException(msg or '%r is not %r' % (first, second))
|
||||
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
|
||||
obect-identity-equality test, not an object equality
|
||||
|
@ -237,7 +261,7 @@ class TestCase(TestCase):
|
|||
if first is second:
|
||||
raise self.failureException(msg or '%r is %r' % (first, second))
|
||||
return first
|
||||
assertNotIdentical = failIfIdentical
|
||||
assertNotIdentical = failIfIdentical = assertIsNot
|
||||
|
||||
|
||||
def failUnlessRaises(self, exception, f, *args, **kwargs):
|
||||
|
@ -300,3 +324,140 @@ class TestCase(TestCase):
|
|||
self.assertTrue(isinstance(theType, type))
|
||||
instance = theType(*constructionArgs)
|
||||
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:
|
||||
def __init__(self, *args):
|
||||
self._ssl_conn = apply(_ssl.Connection, args)
|
||||
self._ssl_conn = _ssl.Connection(*args)
|
||||
self._lock = _RLock()
|
||||
|
||||
for f in ('get_context', 'pending', 'send', 'write', 'recv', 'read',
|
||||
|
|
|
@ -6,4 +6,4 @@
|
|||
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/events.py
|
||||
../sqlalchemy/exc.py
|
||||
../sqlalchemy/inspection.py
|
||||
../sqlalchemy/interfaces.py
|
||||
../sqlalchemy/log.py
|
||||
../sqlalchemy/pool.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/testing/engines.py
|
||||
../sqlalchemy/testing/schema.py
|
||||
../sqlalchemy/testing/pickleable.py
|
||||
../sqlalchemy/testing/fixtures.py
|
||||
../sqlalchemy/dialects/__init__.py
|
||||
../sqlalchemy/dialects/postgres.py
|
||||
../sqlalchemy/dialects/drizzle/__init__.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/assertions.py
|
||||
../sqlalchemy/testing/assertsql.py
|
||||
../sqlalchemy/testing/config.py
|
||||
../sqlalchemy/testing/warnings.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/runner.py
|
||||
../sqlalchemy/testing/assertions.py
|
||||
../sqlalchemy/testing/profiling.py
|
||||
../sqlalchemy/testing/mock.py
|
||||
../sqlalchemy/testing/exclusions.py
|
||||
../sqlalchemy/testing/schema.py
|
||||
../sqlalchemy/testing/util.py
|
||||
../sqlalchemy/testing/entities.py
|
||||
../sqlalchemy/testing/plugin/noseplugin.py
|
||||
../sqlalchemy/testing/warnings.py
|
||||
../sqlalchemy/testing/plugin/__init__.py
|
||||
../sqlalchemy/testing/plugin/pytestplugin.py
|
||||
../sqlalchemy/testing/plugin/noseplugin.py
|
||||
../sqlalchemy/testing/plugin/plugin_base.py
|
||||
../sqlalchemy/testing/suite/test_insert.py
|
||||
../sqlalchemy/testing/suite/test_results.py
|
||||
../sqlalchemy/testing/plugin/pytestplugin.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_sequence.py
|
||||
../sqlalchemy/testing/suite/test_types.py
|
||||
../sqlalchemy/testing/suite/test_update_delete.py
|
||||
../sqlalchemy/testing/suite/test_reflection.py
|
||||
../sqlalchemy/testing/suite/test_ddl.py
|
||||
../sqlalchemy/orm/persistence.py
|
||||
../sqlalchemy/orm/interfaces.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/__init__.py
|
||||
../sqlalchemy/util/_collections.py
|
||||
../sqlalchemy/util/compat.py
|
||||
../sqlalchemy/util/deprecations.py
|
||||
../sqlalchemy/util/langhelpers.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/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__/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__/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/testing/__pycache__/engines.cpython-34.pyc
|
||||
../sqlalchemy/testing/__pycache__/schema.cpython-34.pyc
|
||||
../sqlalchemy/testing/__pycache__/pickleable.cpython-34.pyc
|
||||
../sqlalchemy/testing/__pycache__/fixtures.cpython-34.pyc
|
||||
../sqlalchemy/dialects/__pycache__/__init__.cpython-34.pyc
|
||||
../sqlalchemy/dialects/__pycache__/postgres.cpython-34.pyc
|
||||
../sqlalchemy/dialects/drizzle/__pycache__/__init__.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__/assertions.cpython-34.pyc
|
||||
../sqlalchemy/testing/__pycache__/assertsql.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__/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__/runner.cpython-34.pyc
|
||||
../sqlalchemy/testing/__pycache__/assertions.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__/schema.cpython-34.pyc
|
||||
../sqlalchemy/testing/__pycache__/util.cpython-34.pyc
|
||||
../sqlalchemy/testing/__pycache__/entities.cpython-34.pyc
|
||||
../sqlalchemy/testing/plugin/__pycache__/noseplugin.cpython-34.pyc
|
||||
../sqlalchemy/testing/__pycache__/warnings.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/suite/__pycache__/test_insert.cpython-34.pyc
|
||||
../sqlalchemy/testing/suite/__pycache__/test_results.cpython-34.pyc
|
||||
../sqlalchemy/testing/plugin/__pycache__/pytestplugin.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_sequence.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_reflection.cpython-34.pyc
|
||||
../sqlalchemy/testing/suite/__pycache__/test_ddl.cpython-34.pyc
|
||||
../sqlalchemy/orm/__pycache__/persistence.cpython-34.pyc
|
||||
../sqlalchemy/orm/__pycache__/interfaces.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__/__init__.cpython-34.pyc
|
||||
../sqlalchemy/util/__pycache__/_collections.cpython-34.pyc
|
||||
../sqlalchemy/util/__pycache__/compat.cpython-34.pyc
|
||||
../sqlalchemy/util/__pycache__/deprecations.cpython-34.pyc
|
||||
../sqlalchemy/util/__pycache__/langhelpers.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/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/cresultproxy.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
|
||||
Name: cffi
|
||||
Version: 0.8.6
|
||||
Version: 1.3.0
|
||||
Summary: Foreign Function Interface for Python calling C code.
|
||||
Home-page: http://cffi.readthedocs.org
|
||||
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.2
|
||||
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/recompiler.py
|
||||
../cffi/verifier.py
|
||||
../cffi/backend_ctypes.py
|
||||
../cffi/api.py
|
||||
../cffi/ffiplatform.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/__pycache__/lock.cpython-34.pyc
|
||||
../cffi/__pycache__/backend_ctypes.cpython-34.pyc
|
||||
../cffi/__pycache__/__init__.cpython-34.pyc
|
||||
../cffi/__pycache__/ffiplatform.cpython-34.pyc
|
||||
../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/__init__.py
|
||||
../cffi/commontypes.py
|
||||
../cffi/_cffi_include.h
|
||||
../cffi/parse_c_type.h
|
||||
../cffi/__pycache__/gc_weakref.cpython-34.pyc
|
||||
../cffi/__pycache__/recompiler.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__/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__/__init__.cpython-34.pyc
|
||||
../cffi/__pycache__/commontypes.cpython-34.pyc
|
||||
../_cffi_backend.cpython-34m.so
|
||||
./
|
||||
dependency_links.txt
|
||||
PKG-INFO
|
||||
SOURCES.txt
|
||||
entry_points.txt
|
||||
not-zip-safe
|
||||
top_level.txt
|
||||
dependency_links.txt
|
||||
requires.txt
|
||||
top_level.txt
|
|
@ -1,2 +1,2 @@
|
|||
cffi
|
||||
_cffi_backend
|
||||
cffi
|
|
@ -4,5 +4,10 @@ __all__ = ['FFI', 'VerificationError', 'VerificationMissing', 'CDefError',
|
|||
from .api import FFI, CDefError, FFIError
|
||||
from .ffiplatform import VerificationError, VerificationMissing
|
||||
|
||||
__version__ = "0.8.6"
|
||||
__version_info__ = (0, 8, 6)
|
||||
__version__ = "1.3.0"
|
||||
__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.
|
||||
import _cffi_backend as backend
|
||||
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
|
||||
# 'backend=backend_ctypes.CTypesBackend()', but don't
|
||||
# rely on it! It's probably not going to work well.)
|
||||
|
@ -69,6 +70,8 @@ class FFI(object):
|
|||
self._function_caches = []
|
||||
self._libraries = []
|
||||
self._cdefsources = []
|
||||
self._included_ffis = []
|
||||
self._windows_unicode = None
|
||||
if hasattr(backend, 'set_ffi'):
|
||||
backend.set_ffi(self)
|
||||
for name in backend.__dict__:
|
||||
|
@ -77,6 +80,7 @@ class FFI(object):
|
|||
#
|
||||
with self._lock:
|
||||
self.BVoidP = self._get_cached_btype(model.voidp_type)
|
||||
self.BCharA = self._get_cached_btype(model.char_array_type)
|
||||
if isinstance(backend, types.ModuleType):
|
||||
# _cffi_backend: attach these constants to the class
|
||||
if not hasattr(FFI, 'NULL'):
|
||||
|
@ -105,6 +109,11 @@ class FFI(object):
|
|||
if override:
|
||||
for cache in self._function_caches:
|
||||
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):
|
||||
"""Load and return a dynamic library identified by 'name'.
|
||||
|
@ -189,13 +198,16 @@ class FFI(object):
|
|||
cdecl = self._typeof(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
|
||||
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):
|
||||
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):
|
||||
"""Allocate an instance according to the specified C type and
|
||||
|
@ -224,6 +236,30 @@ class FFI(object):
|
|||
cdecl = self._typeof(cdecl)
|
||||
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):
|
||||
"""Similar to a C cast: returns an instance of the named C
|
||||
type initialized with the given 'source'. The source is
|
||||
|
@ -264,7 +300,33 @@ class FFI(object):
|
|||
"""
|
||||
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
|
||||
callback object. 'cdecl' must name a C function pointer type.
|
||||
The callback invokes the specified 'python_callable' (which may
|
||||
|
@ -276,7 +338,8 @@ class FFI(object):
|
|||
if not callable(python_callable):
|
||||
raise TypeError("the 'python_callable' argument "
|
||||
"is not callable")
|
||||
return self._backend.callback(cdecl, python_callable, error)
|
||||
return self._backend.callback(cdecl, python_callable,
|
||||
error, onerror)
|
||||
if isinstance(cdecl, basestring):
|
||||
cdecl = self._typeof(cdecl, consider_function_as_funcptr=True)
|
||||
if python_callable is None:
|
||||
|
@ -305,6 +368,13 @@ class FFI(object):
|
|||
data. Later, when this new cdata object is garbage-collected,
|
||||
'destructor(old_cdata_object)' will be called.
|
||||
"""
|
||||
try:
|
||||
gcp = self._backend.gcp
|
||||
except AttributeError:
|
||||
pass
|
||||
else:
|
||||
return gcp(cdata, destructor)
|
||||
#
|
||||
with self._lock:
|
||||
try:
|
||||
gc_weakrefs = self.gc_weakrefs
|
||||
|
@ -335,9 +405,23 @@ class FFI(object):
|
|||
which requires binary compatibility in the signatures.
|
||||
"""
|
||||
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()
|
||||
#
|
||||
# Make a Verifier() and use it to load the library.
|
||||
self.verifier = Verifier(self, source, tmpdir, **kwargs)
|
||||
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)
|
||||
return lib
|
||||
|
||||
|
@ -356,15 +440,29 @@ class FFI(object):
|
|||
with self._lock:
|
||||
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'>.
|
||||
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, 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)
|
||||
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):
|
||||
"""Includes the typedefs, structs, unions and enums defined
|
||||
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
|
||||
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 self._lock:
|
||||
self._parser.include(ffi_to_include._parser)
|
||||
self._cdefsources.append('[')
|
||||
self._cdefsources.extend(ffi_to_include._cdefsources)
|
||||
self._cdefsources.append(']')
|
||||
self._included_ffis.append(ffi_to_include)
|
||||
|
||||
def new_handle(self, x):
|
||||
return self._backend.newp_handle(self.BVoidP, x)
|
||||
|
@ -387,6 +492,112 @@ class FFI(object):
|
|||
def from_handle(self, 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):
|
||||
if name is None:
|
||||
|
@ -414,7 +625,7 @@ def _make_ffi_library(ffi, libname, flags):
|
|||
def make_accessor_locked(name):
|
||||
key = 'function ' + name
|
||||
if key in ffi._parser._declarations:
|
||||
tp = ffi._parser._declarations[key]
|
||||
tp, _ = ffi._parser._declarations[key]
|
||||
BType = ffi._get_cached_btype(tp)
|
||||
try:
|
||||
value = backendlib.load_function(BType, name)
|
||||
|
@ -425,7 +636,7 @@ def _make_ffi_library(ffi, libname, flags):
|
|||
#
|
||||
key = 'variable ' + name
|
||||
if key in ffi._parser._declarations:
|
||||
tp = ffi._parser._declarations[key]
|
||||
tp, _ = ffi._parser._declarations[key]
|
||||
BType = ffi._get_cached_btype(tp)
|
||||
read_variable = backendlib.read_variable
|
||||
write_variable = backendlib.write_variable
|
||||
|
@ -436,12 +647,23 @@ def _make_ffi_library(ffi, libname, flags):
|
|||
#
|
||||
if not copied_enums:
|
||||
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):
|
||||
continue
|
||||
try:
|
||||
tp.check_not_partial()
|
||||
except Exception as e:
|
||||
error = e
|
||||
continue
|
||||
for enumname, enumval in zip(tp.enumerators, tp.enumvalues):
|
||||
if enumname not in library.__dict__:
|
||||
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():
|
||||
if key not in library.__dict__:
|
||||
library.__dict__[key] = val
|
||||
|
@ -450,6 +672,11 @@ def _make_ffi_library(ffi, libname, flags):
|
|||
if name in library.__dict__:
|
||||
return
|
||||
#
|
||||
key = 'constant ' + name
|
||||
if key in ffi._parser._declarations:
|
||||
raise NotImplementedError("fetching a non-integer constant "
|
||||
"after dlopen()")
|
||||
#
|
||||
raise AttributeError(name)
|
||||
#
|
||||
def make_accessor(name):
|
||||
|
|
|
@ -2,11 +2,10 @@ import ctypes, ctypes.util, operator, sys
|
|||
from . import model
|
||||
|
||||
if sys.version_info < (3,):
|
||||
integer_types = (int, long)
|
||||
bytechr = chr
|
||||
else:
|
||||
unicode = str
|
||||
integer_types = int
|
||||
long = int
|
||||
xrange = range
|
||||
bytechr = lambda num: bytes([num])
|
||||
|
||||
|
@ -169,6 +168,7 @@ class CTypesGenericArray(CTypesData):
|
|||
class CTypesGenericPtr(CTypesData):
|
||||
__slots__ = ['_address', '_as_ctype_ptr']
|
||||
_automatic_casts = False
|
||||
kind = "pointer"
|
||||
|
||||
@classmethod
|
||||
def _newp(cls, init):
|
||||
|
@ -180,7 +180,7 @@ class CTypesGenericPtr(CTypesData):
|
|||
address = 0
|
||||
elif isinstance(source, CTypesData):
|
||||
address = source._cast_to_integer()
|
||||
elif isinstance(source, integer_types):
|
||||
elif isinstance(source, (int, long)):
|
||||
address = source
|
||||
else:
|
||||
raise TypeError("bad type for cast to %r: %r" %
|
||||
|
@ -357,7 +357,7 @@ class CTypesBackend(object):
|
|||
is_signed = (ctype(-1).value == -1)
|
||||
#
|
||||
def _cast_source_to_int(source):
|
||||
if isinstance(source, (integer_types, float)):
|
||||
if isinstance(source, (int, long, float)):
|
||||
source = int(source)
|
||||
elif isinstance(source, CTypesData):
|
||||
source = source._cast_to_integer()
|
||||
|
@ -370,10 +370,12 @@ class CTypesBackend(object):
|
|||
(CTypesPrimitive, type(source).__name__))
|
||||
return source
|
||||
#
|
||||
kind1 = kind
|
||||
class CTypesPrimitive(CTypesGenericPrimitive):
|
||||
__slots__ = ['_value']
|
||||
_ctype = ctype
|
||||
_reftypename = '%s &' % name
|
||||
kind = kind1
|
||||
|
||||
def __init__(self, value):
|
||||
self._value = value
|
||||
|
@ -396,7 +398,7 @@ class CTypesBackend(object):
|
|||
if kind == 'bool':
|
||||
@classmethod
|
||||
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)
|
||||
return cls(bool(source))
|
||||
def __int__(self):
|
||||
|
@ -435,7 +437,7 @@ class CTypesBackend(object):
|
|||
if kind == 'int' or kind == 'byte' or kind == 'bool':
|
||||
@staticmethod
|
||||
def _to_ctypes(x):
|
||||
if not isinstance(x, integer_types):
|
||||
if not isinstance(x, (int, long)):
|
||||
if isinstance(x, CTypesData):
|
||||
x = int(x)
|
||||
else:
|
||||
|
@ -462,7 +464,7 @@ class CTypesBackend(object):
|
|||
if kind == 'float':
|
||||
@staticmethod
|
||||
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" %
|
||||
type(x).__name__)
|
||||
return ctype(x).value
|
||||
|
@ -526,14 +528,14 @@ class CTypesBackend(object):
|
|||
self._own = True
|
||||
|
||||
def __add__(self, other):
|
||||
if isinstance(other, integer_types):
|
||||
if isinstance(other, (int, long)):
|
||||
return self._new_pointer_at(self._address +
|
||||
other * self._bitem_size)
|
||||
else:
|
||||
return NotImplemented
|
||||
|
||||
def __sub__(self, other):
|
||||
if isinstance(other, integer_types):
|
||||
if isinstance(other, (int, long)):
|
||||
return self._new_pointer_at(self._address -
|
||||
other * self._bitem_size)
|
||||
elif type(self) is type(other):
|
||||
|
@ -608,7 +610,7 @@ class CTypesBackend(object):
|
|||
|
||||
def __init__(self, init):
|
||||
if length is None:
|
||||
if isinstance(init, integer_types):
|
||||
if isinstance(init, (int, long)):
|
||||
len1 = init
|
||||
init = None
|
||||
elif kind == 'char' and isinstance(init, bytes):
|
||||
|
@ -683,7 +685,7 @@ class CTypesBackend(object):
|
|||
return CTypesPtr._arg_to_ctypes(value)
|
||||
|
||||
def __add__(self, other):
|
||||
if isinstance(other, integer_types):
|
||||
if isinstance(other, (int, long)):
|
||||
return CTypesPtr._new_pointer_at(
|
||||
ctypes.addressof(self._blob) +
|
||||
other * ctypes.sizeof(BItem._ctype))
|
||||
|
@ -703,12 +705,13 @@ class CTypesBackend(object):
|
|||
class struct_or_union(base_ctypes_class):
|
||||
pass
|
||||
struct_or_union.__name__ = '%s_%s' % (kind, name)
|
||||
kind1 = kind
|
||||
#
|
||||
class CTypesStructOrUnion(CTypesBaseStructOrUnion):
|
||||
__slots__ = ['_blob']
|
||||
_ctype = struct_or_union
|
||||
_reftypename = '%s &' % (name,)
|
||||
_kind = kind
|
||||
_kind = kind = kind1
|
||||
#
|
||||
CTypesStructOrUnion._fix_class()
|
||||
return CTypesStructOrUnion
|
||||
|
@ -986,7 +989,8 @@ class CTypesBackend(object):
|
|||
def cast(self, BType, 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)
|
||||
|
||||
typeof = type
|
||||
|
@ -994,27 +998,42 @@ class CTypesBackend(object):
|
|||
def getcname(self, BType, replace_with):
|
||||
return BType._get_c_name(replace_with)
|
||||
|
||||
def typeoffsetof(self, BType, fieldname):
|
||||
if fieldname is not None and issubclass(BType, CTypesGenericPtr):
|
||||
def typeoffsetof(self, BType, fieldname, num=0):
|
||||
if isinstance(fieldname, str):
|
||||
if num == 0 and issubclass(BType, CTypesGenericPtr):
|
||||
BType = BType._BItem
|
||||
if not issubclass(BType, CTypesBaseStructOrUnion):
|
||||
raise TypeError("expected a struct or union ctype")
|
||||
if fieldname is None:
|
||||
return (BType, 0)
|
||||
else:
|
||||
BField = BType._bfield_types[fieldname]
|
||||
if BField is Ellipsis:
|
||||
raise TypeError("not supported for bitfields")
|
||||
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):
|
||||
ptr = ctypes.pointer(type(cdata)._to_ctypes(cdata))
|
||||
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)
|
||||
else:
|
||||
raise TypeError("expected a <cdata 'struct-or-union'>")
|
||||
if offset != 0:
|
||||
if offset:
|
||||
ptr = ctypes.cast(
|
||||
ctypes.c_void_p(
|
||||
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]))
|
||||
elif result in model.PrimitiveType.ALL_PRIMITIVE_TYPES:
|
||||
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:
|
||||
if commontype == result:
|
||||
raise api.FFIError("Unsupported type: %r. Please file a bug "
|
||||
|
@ -86,8 +89,6 @@ def win_common_types(maxsize):
|
|||
"ULONGLONG": "unsigned long long",
|
||||
"WCHAR": "wchar_t",
|
||||
"SHORT": "short",
|
||||
"TBYTE": "WCHAR",
|
||||
"TCHAR": "WCHAR",
|
||||
"UCHAR": "unsigned char",
|
||||
"UINT": "unsigned int",
|
||||
"UINT8": "unsigned char",
|
||||
|
@ -157,14 +158,12 @@ def win_common_types(maxsize):
|
|||
|
||||
"LPCVOID": model.const_voidp_type,
|
||||
"LPCWSTR": "const WCHAR *",
|
||||
"LPCTSTR": "LPCWSTR",
|
||||
"LPDWORD": "DWORD *",
|
||||
"LPHANDLE": "HANDLE *",
|
||||
"LPINT": "int *",
|
||||
"LPLONG": "long *",
|
||||
"LPSTR": "CHAR *",
|
||||
"LPWSTR": "WCHAR *",
|
||||
"LPTSTR": "LPWSTR",
|
||||
"LPVOID": model.voidp_type,
|
||||
"LPWORD": "WORD *",
|
||||
"LRESULT": "LONG_PTR",
|
||||
|
@ -173,7 +172,6 @@ def win_common_types(maxsize):
|
|||
"PBYTE": "BYTE *",
|
||||
"PCHAR": "CHAR *",
|
||||
"PCSTR": "const CHAR *",
|
||||
"PCTSTR": "LPCWSTR",
|
||||
"PCWSTR": "const WCHAR *",
|
||||
"PDWORD": "DWORD *",
|
||||
"PDWORDLONG": "DWORDLONG *",
|
||||
|
@ -200,9 +198,6 @@ def win_common_types(maxsize):
|
|||
"PSIZE_T": "SIZE_T *",
|
||||
"PSSIZE_T": "SSIZE_T *",
|
||||
"PSTR": "CHAR *",
|
||||
"PTBYTE": "TBYTE *",
|
||||
"PTCHAR": "TCHAR *",
|
||||
"PTSTR": "LPWSTR",
|
||||
"PUCHAR": "UCHAR *",
|
||||
"PUHALF_PTR": "UHALF_PTR *",
|
||||
"PUINT": "UINT *",
|
||||
|
@ -240,6 +235,15 @@ def win_common_types(maxsize):
|
|||
"USN": "LONGLONG",
|
||||
"VOID": model.void_type,
|
||||
"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
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
from . import api, model
|
||||
from .commontypes import COMMON_TYPES, resolve_common_type
|
||||
try:
|
||||
|
@ -16,15 +15,20 @@ try:
|
|||
except ImportError:
|
||||
lock = None
|
||||
|
||||
_r_comment = re.compile(r"/\*.*?\*/|//.*?$", re.DOTALL | re.MULTILINE)
|
||||
_r_define = re.compile(r"^\s*#\s*define\s+([A-Za-z_][A-Za-z_0-9]*)\s+(.*?)$",
|
||||
re.MULTILINE)
|
||||
_r_comment = re.compile(r"/\*.*?\*/|//([^\n\\]|\\.)*?$",
|
||||
re.DOTALL | 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_enum_dotdotdot = re.compile(r"__dotdotdot\d+__$")
|
||||
_r_partial_array = re.compile(r"\[\s*\.\.\.\s*\]")
|
||||
_r_words = re.compile(r"\w+|\S")
|
||||
_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():
|
||||
global _parser_cache
|
||||
|
@ -40,8 +44,17 @@ def _preprocess(csource):
|
|||
macros = {}
|
||||
for match in _r_define.finditer(csource):
|
||||
macroname, macrovalue = match.groups()
|
||||
macrovalue = macrovalue.replace('\\\n', '').strip()
|
||||
macros[macroname] = macrovalue
|
||||
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__]"
|
||||
csource = _r_partial_array.sub('[__dotdotdotarray__]', csource)
|
||||
# Replace "...}" with "__dotdotdotNUM__}". This construction should
|
||||
|
@ -73,9 +86,13 @@ def _common_type_names(csource):
|
|||
# but should be fine for all the 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('typedef')
|
||||
words_used = set()
|
||||
is_typedef = False
|
||||
paren = 0
|
||||
previous_word = ''
|
||||
for word in _r_words.findall(csource):
|
||||
if word in look_for_words:
|
||||
|
@ -86,6 +103,15 @@ def _common_type_names(csource):
|
|||
is_typedef = False
|
||||
elif word == 'typedef':
|
||||
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
|
||||
words_used.add(word)
|
||||
previous_word = word
|
||||
|
@ -96,11 +122,14 @@ class Parser(object):
|
|||
|
||||
def __init__(self):
|
||||
self._declarations = {}
|
||||
self._included_declarations = set()
|
||||
self._anonymous_counter = 0
|
||||
self._structnode2type = weakref.WeakKeyDictionary()
|
||||
self._override = False
|
||||
self._packed = False
|
||||
self._int_constants = {}
|
||||
self._recomplete = []
|
||||
self._uses_new_feature = None
|
||||
|
||||
def _parse(self, csource):
|
||||
csource, macros = _preprocess(csource)
|
||||
|
@ -187,9 +216,10 @@ class Parser(object):
|
|||
if not decl.name:
|
||||
raise api.CDefError("typedef does not declare any name",
|
||||
decl)
|
||||
quals = 0
|
||||
if (isinstance(decl.type.type, pycparser.c_ast.IdentifierType)
|
||||
and decl.type.type.names == ['__dotdotdot__']):
|
||||
realtype = model.unknown_type(decl.name)
|
||||
and decl.type.type.names[-1] == '__dotdotdot__'):
|
||||
realtype = self._get_unknown_type(decl)
|
||||
elif (isinstance(decl.type, pycparser.c_ast.PtrDecl) and
|
||||
isinstance(decl.type.type, pycparser.c_ast.TypeDecl) and
|
||||
isinstance(decl.type.type.type,
|
||||
|
@ -197,8 +227,9 @@ class Parser(object):
|
|||
decl.type.type.type.names == ['__dotdotdot__']):
|
||||
realtype = model.unknown_ptr_type(decl.name)
|
||||
else:
|
||||
realtype = self._get_type(decl.type, name=decl.name)
|
||||
self._declare('typedef ' + decl.name, realtype)
|
||||
realtype, quals = self._get_type_and_quals(
|
||||
decl.type, name=decl.name)
|
||||
self._declare('typedef ' + decl.name, realtype, quals=quals)
|
||||
else:
|
||||
raise api.CDefError("unrecognized construct", decl)
|
||||
except api.FFIError as e:
|
||||
|
@ -209,60 +240,84 @@ class Parser(object):
|
|||
|
||||
def _add_constants(self, key, val):
|
||||
if key in self._int_constants:
|
||||
if self._int_constants[key] == val:
|
||||
return # ignore identical double declarations
|
||||
raise api.FFIError(
|
||||
"multiple declarations of constant: %s" % (key,))
|
||||
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):
|
||||
for key, value in macros.items():
|
||||
value = value.strip()
|
||||
match = _r_int_literal.search(value)
|
||||
if match is not None:
|
||||
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)
|
||||
if _r_int_literal.match(value):
|
||||
self._add_integer_constant(key, value)
|
||||
elif value == '...':
|
||||
self._declare('macro ' + key, value)
|
||||
else:
|
||||
raise api.CDefError('only supports the syntax "#define '
|
||||
'%s ..." (literally) or "#define '
|
||||
'%s 0x1FF" for now' % (key, key))
|
||||
raise api.CDefError(
|
||||
'only supports one of the following syntax:\n'
|
||||
' #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):
|
||||
node = decl.type
|
||||
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)
|
||||
tp = self._get_type_pointer(tp)
|
||||
tp = self._get_type_pointer(tp, quals)
|
||||
self._declare('function ' + decl.name, tp)
|
||||
else:
|
||||
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)
|
||||
elif isinstance(node, pycparser.c_ast.Union):
|
||||
if node.decls is not None:
|
||||
self._get_struct_union_enum_type('union', node)
|
||||
elif isinstance(node, pycparser.c_ast.Enum):
|
||||
if node.values is not None:
|
||||
self._get_struct_union_enum_type('enum', node)
|
||||
elif not decl.name:
|
||||
raise api.CDefError("construct does not declare any variable",
|
||||
decl)
|
||||
#
|
||||
if decl.name:
|
||||
tp = self._get_type(node, partial_length_ok=True)
|
||||
if self._is_constant_globalvar(node):
|
||||
self._declare('constant ' + decl.name, tp)
|
||||
tp, quals = self._get_type_and_quals(node,
|
||||
partial_length_ok=True)
|
||||
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:
|
||||
self._declare('variable ' + decl.name, tp)
|
||||
self._declare('variable ' + decl.name, tp, quals=quals)
|
||||
|
||||
def parse_type(self, cdecl):
|
||||
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]
|
||||
if isinstance(exprnode, pycparser.c_ast.ID):
|
||||
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 self._declarations[name] is obj:
|
||||
prevobj, prevquals = self._declarations[name]
|
||||
if prevobj is obj and prevquals == quals:
|
||||
return
|
||||
if not self._override:
|
||||
raise api.FFIError(
|
||||
"multiple declarations of %s (for interactive usage, "
|
||||
"try cdef(xx, override=True))" % (name,))
|
||||
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):
|
||||
return type.as_function_pointer()
|
||||
if const:
|
||||
return model.ConstPointerType(type)
|
||||
return model.PointerType(type)
|
||||
if (isinstance(type, model.StructOrUnionOrEnum) and
|
||||
type.name.startswith('$') and type.name[1:].isdigit() and
|
||||
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
|
||||
if (isinstance(typenode, pycparser.c_ast.TypeDecl) and
|
||||
isinstance(typenode.type, pycparser.c_ast.IdentifierType) and
|
||||
len(typenode.type.names) == 1 and
|
||||
('typedef ' + typenode.type.names[0]) in self._declarations):
|
||||
type = self._declarations['typedef ' + typenode.type.names[0]]
|
||||
return type
|
||||
tp, quals = self._declarations['typedef ' + typenode.type.names[0]]
|
||||
quals |= self._extract_quals(typenode)
|
||||
return tp, quals
|
||||
#
|
||||
if isinstance(typenode, pycparser.c_ast.ArrayDecl):
|
||||
# array type
|
||||
|
@ -306,15 +378,19 @@ class Parser(object):
|
|||
else:
|
||||
length = self._parse_constant(
|
||||
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):
|
||||
# pointer type
|
||||
const = (isinstance(typenode.type, pycparser.c_ast.TypeDecl)
|
||||
and 'const' in typenode.type.quals)
|
||||
return self._get_type_pointer(self._get_type(typenode.type), const)
|
||||
itemtype, itemquals = self._get_type_and_quals(typenode.type)
|
||||
tp = self._get_type_pointer(itemtype, itemquals, declname=name)
|
||||
quals = self._extract_quals(typenode)
|
||||
return tp, quals
|
||||
#
|
||||
if isinstance(typenode, pycparser.c_ast.TypeDecl):
|
||||
quals = self._extract_quals(typenode)
|
||||
type = typenode.type
|
||||
if isinstance(type, pycparser.c_ast.IdentifierType):
|
||||
# assume a primitive type. get it from .names, but reduce
|
||||
|
@ -342,35 +418,38 @@ class Parser(object):
|
|||
names = newnames + names
|
||||
ident = ' '.join(names)
|
||||
if ident == 'void':
|
||||
return model.void_type
|
||||
return model.void_type, quals
|
||||
if ident == '__dotdotdot__':
|
||||
raise api.FFIError(':%d: bad usage of "..."' %
|
||||
typenode.coord.line)
|
||||
return resolve_common_type(ident)
|
||||
return resolve_common_type(ident), quals
|
||||
#
|
||||
if isinstance(type, pycparser.c_ast.Struct):
|
||||
# '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):
|
||||
# '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):
|
||||
# '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):
|
||||
# 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
|
||||
if isinstance(typenode, pycparser.c_ast.Struct):
|
||||
return self._get_struct_union_enum_type('struct', typenode, name,
|
||||
nested=True)
|
||||
nested=True), 0
|
||||
if isinstance(typenode, pycparser.c_ast.Union):
|
||||
return self._get_struct_union_enum_type('union', typenode, name,
|
||||
nested=True)
|
||||
nested=True), 0
|
||||
#
|
||||
raise api.FFIError(":%d: bad or unsupported type declaration" %
|
||||
typenode.coord.line)
|
||||
|
@ -389,31 +468,28 @@ class Parser(object):
|
|||
raise api.CDefError(
|
||||
"%s: a function with only '(...)' as argument"
|
||||
" is not correct C" % (funcname or 'in expression'))
|
||||
elif (len(params) == 1 and
|
||||
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))
|
||||
args = [self._as_func_arg(*self._get_type_and_quals(argdeclnode.type))
|
||||
for argdeclnode in params]
|
||||
result = self._get_type(typenode.type)
|
||||
return model.RawFunctionType(tuple(args), result, ellipsis)
|
||||
if not ellipsis and args == [model.void_type]:
|
||||
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):
|
||||
return model.PointerType(type.item)
|
||||
return model.PointerType(type.item, quals)
|
||||
elif isinstance(type, model.RawFunctionType):
|
||||
return type.as_function_pointer()
|
||||
else:
|
||||
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):
|
||||
# First, a level of caching on the exact 'type' node of the AST.
|
||||
# This is obscure, but needed because pycparser "unrolls" declarations
|
||||
|
@ -452,7 +528,7 @@ class Parser(object):
|
|||
else:
|
||||
explicit_name = name
|
||||
key = '%s %s' % (kind, name)
|
||||
tp = self._declarations.get(key, None)
|
||||
tp, _ = self._declarations.get(key, (None, None))
|
||||
#
|
||||
if tp is None:
|
||||
if kind == 'struct':
|
||||
|
@ -460,6 +536,8 @@ class Parser(object):
|
|||
elif kind == 'union':
|
||||
tp = model.UnionType(explicit_name, None, None, None)
|
||||
elif kind == 'enum':
|
||||
if explicit_name == '__dotdotdot__':
|
||||
raise CDefError("Enums cannot be declared with ...")
|
||||
tp = self._build_enum_type(explicit_name, type.values)
|
||||
else:
|
||||
raise AssertionError("kind = %r" % (kind,))
|
||||
|
@ -492,6 +570,7 @@ class Parser(object):
|
|||
fldnames = []
|
||||
fldtypes = []
|
||||
fldbitsize = []
|
||||
fldquals = []
|
||||
for decl in type.decls:
|
||||
if (isinstance(decl.type, pycparser.c_ast.IdentifierType) and
|
||||
''.join(decl.type.names) == '__dotdotdot__'):
|
||||
|
@ -505,7 +584,8 @@ class Parser(object):
|
|||
else:
|
||||
bitsize = self._parse_constant(decl.bitsize)
|
||||
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:
|
||||
self._make_partial(tp, nested)
|
||||
if isinstance(type, model.StructType) and type.partial:
|
||||
|
@ -513,14 +593,19 @@ class Parser(object):
|
|||
fldnames.append(decl.name or '')
|
||||
fldtypes.append(type)
|
||||
fldbitsize.append(bitsize)
|
||||
fldquals.append(fqual)
|
||||
tp.fldnames = tuple(fldnames)
|
||||
tp.fldtypes = tuple(fldtypes)
|
||||
tp.fldbitsize = tuple(fldbitsize)
|
||||
tp.fldquals = tuple(fldquals)
|
||||
if fldbitsize != [-1] * len(fldbitsize):
|
||||
if isinstance(tp, model.StructType) and tp.partial:
|
||||
raise NotImplementedError("%s: using both bitfields and '...;'"
|
||||
% (tp,))
|
||||
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
|
||||
|
||||
def _make_partial(self, tp, nested):
|
||||
|
@ -532,9 +617,24 @@ class Parser(object):
|
|||
|
||||
def _parse_constant(self, exprnode, partial_length_ok=False):
|
||||
# for now, limited to expressions that are an immediate number
|
||||
# or negative number
|
||||
# or positive/negative number
|
||||
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
|
||||
exprnode.op == '-'):
|
||||
|
@ -555,19 +655,21 @@ class Parser(object):
|
|||
|
||||
def _build_enum_type(self, explicit_name, decls):
|
||||
if decls is not None:
|
||||
enumerators1 = [enum.name for enum in decls.enumerators]
|
||||
enumerators = [s for s in enumerators1
|
||||
if not _r_enum_dotdotdot.match(s)]
|
||||
partial = len(enumerators) < len(enumerators1)
|
||||
enumerators = tuple(enumerators)
|
||||
partial = False
|
||||
enumerators = []
|
||||
enumvalues = []
|
||||
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:
|
||||
nextenumvalue = self._parse_constant(enum.value)
|
||||
enumerators.append(enum.name)
|
||||
enumvalues.append(nextenumvalue)
|
||||
self._add_constants(enum.name, nextenumvalue)
|
||||
nextenumvalue += 1
|
||||
enumerators = tuple(enumerators)
|
||||
enumvalues = tuple(enumvalues)
|
||||
tp = model.EnumType(explicit_name, enumerators, enumvalues)
|
||||
tp.partial = partial
|
||||
|
@ -576,9 +678,35 @@ class Parser(object):
|
|||
return tp
|
||||
|
||||
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]
|
||||
if kind in ('typedef', 'struct', 'union', 'enum'):
|
||||
self._declare(name, tp)
|
||||
if kind in ('struct', 'union', 'enum', 'anonymous', 'typedef'):
|
||||
self._declare(name, tp, included=True, quals=quals)
|
||||
for k, v in other._int_constants.items():
|
||||
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):
|
||||
|
@ -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):
|
||||
from distutils.core import Extension
|
||||
allsources = [srcfilename]
|
||||
|
|
|
@ -2,18 +2,21 @@ from weakref import ref
|
|||
|
||||
|
||||
class GcWeakrefs(object):
|
||||
# code copied and adapted from WeakKeyDictionary.
|
||||
|
||||
def __init__(self, ffi):
|
||||
self.ffi = ffi
|
||||
self.data = data = {}
|
||||
def remove(k):
|
||||
destructor, cdata = data.pop(k)
|
||||
destructor(cdata)
|
||||
self.remove = remove
|
||||
self.data = {}
|
||||
|
||||
def build(self, cdata, destructor):
|
||||
# make a new cdata of the same type as the original one
|
||||
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
|
||||
|
|
|
@ -1,14 +1,29 @@
|
|||
import types
|
||||
import types, sys
|
||||
import weakref
|
||||
|
||||
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):
|
||||
is_array_type = 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
|
||||
assert result.count('&') == 1
|
||||
# some logic duplication with ffi.getctype()... :-(
|
||||
|
@ -18,6 +33,7 @@ class BaseTypeByIdentity(object):
|
|||
replace_with = '(%s)' % replace_with
|
||||
elif not replace_with[0] in '[(':
|
||||
replace_with = ' ' + replace_with
|
||||
replace_with = qualify(quals, replace_with)
|
||||
result = result.replace('&', replace_with)
|
||||
if '$' in result:
|
||||
from .ffiplatform import VerificationError
|
||||
|
@ -32,6 +48,9 @@ class BaseTypeByIdentity(object):
|
|||
def has_c_name(self):
|
||||
return '$' not in self._get_c_name()
|
||||
|
||||
def is_integer_type(self):
|
||||
return False
|
||||
|
||||
def get_cached_btype(self, ffi, finishlist, can_delay=False):
|
||||
try:
|
||||
BType = ffi._cached_btypes[self]
|
||||
|
@ -73,7 +92,11 @@ class VoidType(BaseType):
|
|||
void_type = VoidType()
|
||||
|
||||
|
||||
class PrimitiveType(BaseType):
|
||||
class BasePrimitiveType(BaseType):
|
||||
pass
|
||||
|
||||
|
||||
class PrimitiveType(BasePrimitiveType):
|
||||
_attrs_ = ('name',)
|
||||
|
||||
ALL_PRIMITIVE_TYPES = {
|
||||
|
@ -102,8 +125,26 @@ class PrimitiveType(BaseType):
|
|||
'uint32_t': 'i',
|
||||
'int64_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',
|
||||
'uintptr_t': 'i',
|
||||
'intmax_t': 'i',
|
||||
'uintmax_t': 'i',
|
||||
'ptrdiff_t': 'i',
|
||||
'size_t': 'i',
|
||||
'ssize_t': 'i',
|
||||
|
@ -125,19 +166,48 @@ class PrimitiveType(BaseType):
|
|||
return global_cache(self, ffi, 'new_primitive_type', self.name)
|
||||
|
||||
|
||||
class BaseFunctionType(BaseType):
|
||||
_attrs_ = ('args', 'result', 'ellipsis')
|
||||
class UnknownIntegerType(BasePrimitiveType):
|
||||
_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.result = result
|
||||
self.ellipsis = ellipsis
|
||||
self.abi = abi
|
||||
#
|
||||
reprargs = [arg._get_c_name() for arg in self.args]
|
||||
if self.ellipsis:
|
||||
reprargs.append('...')
|
||||
reprargs = reprargs or ['void']
|
||||
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.result.c_name_with_marker.replace('&', replace_with))
|
||||
|
||||
|
@ -155,7 +225,7 @@ class RawFunctionType(BaseFunctionType):
|
|||
"type, not a pointer-to-function type" % (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):
|
||||
|
@ -166,21 +236,29 @@ class FunctionPtrType(BaseFunctionType):
|
|||
args = []
|
||||
for tp in self.args:
|
||||
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',
|
||||
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):
|
||||
_attrs_ = ('totype',)
|
||||
_base_pattern = " *&"
|
||||
_base_pattern_array = "(*&)"
|
||||
_attrs_ = ('totype', 'quals')
|
||||
|
||||
def __init__(self, totype):
|
||||
def __init__(self, totype, quals=0):
|
||||
self.totype = totype
|
||||
self.quals = quals
|
||||
extra = qualify(quals, " *&")
|
||||
if totype.is_array_type:
|
||||
extra = self._base_pattern_array
|
||||
else:
|
||||
extra = self._base_pattern
|
||||
extra = "(%s)" % (extra.lstrip(),)
|
||||
self.c_name_with_marker = totype.c_name_with_marker.replace('&', extra)
|
||||
|
||||
def build_backend_type(self, ffi, finishlist):
|
||||
|
@ -189,10 +267,8 @@ class PointerType(BaseType):
|
|||
|
||||
voidp_type = PointerType(void_type)
|
||||
|
||||
|
||||
class ConstPointerType(PointerType):
|
||||
_base_pattern = " const *&"
|
||||
_base_pattern_array = "(const *&)"
|
||||
def ConstPointerType(totype):
|
||||
return PointerType(totype, Q_CONST)
|
||||
|
||||
const_voidp_type = ConstPointerType(void_type)
|
||||
|
||||
|
@ -200,8 +276,8 @@ const_voidp_type = ConstPointerType(void_type)
|
|||
class NamedPointerType(PointerType):
|
||||
_attrs_ = ('totype', 'name')
|
||||
|
||||
def __init__(self, totype, name):
|
||||
PointerType.__init__(self, totype)
|
||||
def __init__(self, totype, name, quals=0):
|
||||
PointerType.__init__(self, totype, quals)
|
||||
self.name = name
|
||||
self.c_name_with_marker = name + '&'
|
||||
|
||||
|
@ -219,7 +295,7 @@ class ArrayType(BaseType):
|
|||
elif length == '...':
|
||||
brackets = '&[/*...*/]'
|
||||
else:
|
||||
brackets = '&[%d]' % length
|
||||
brackets = '&[%s]' % length
|
||||
self.c_name_with_marker = (
|
||||
self.item.c_name_with_marker.replace('&', brackets))
|
||||
|
||||
|
@ -235,6 +311,8 @@ class ArrayType(BaseType):
|
|||
BPtrItem = PointerType(self.item).get_cached_btype(ffi, finishlist)
|
||||
return global_cache(self, ffi, 'new_array_type', BPtrItem, self.length)
|
||||
|
||||
char_array_type = ArrayType(PrimitiveType('char'), None)
|
||||
|
||||
|
||||
class StructOrUnionOrEnum(BaseTypeByIdentity):
|
||||
_attrs_ = ('name',)
|
||||
|
@ -255,26 +333,38 @@ class StructOrUnionOrEnum(BaseTypeByIdentity):
|
|||
|
||||
class StructOrUnion(StructOrUnionOrEnum):
|
||||
fixedlayout = None
|
||||
completed = False
|
||||
completed = 0
|
||||
partial = False
|
||||
packed = False
|
||||
|
||||
def __init__(self, name, fldnames, fldtypes, fldbitsize):
|
||||
def __init__(self, name, fldnames, fldtypes, fldbitsize, fldquals=None):
|
||||
self.name = name
|
||||
self.fldnames = fldnames
|
||||
self.fldtypes = fldtypes
|
||||
self.fldbitsize = fldbitsize
|
||||
self.fldquals = fldquals
|
||||
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):
|
||||
for name, type, bitsize in zip(self.fldnames, self.fldtypes,
|
||||
self.fldbitsize):
|
||||
fldquals = self.fldquals
|
||||
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):
|
||||
# nested anonymous struct/union
|
||||
for result in type.enumfields():
|
||||
yield result
|
||||
else:
|
||||
yield (name, type, bitsize)
|
||||
yield (name, type, bitsize, quals)
|
||||
|
||||
def force_flatten(self):
|
||||
# force the struct or union to have a declaration that lists
|
||||
|
@ -283,13 +373,16 @@ class StructOrUnion(StructOrUnionOrEnum):
|
|||
names = []
|
||||
types = []
|
||||
bitsizes = []
|
||||
for name, type, bitsize in self.enumfields():
|
||||
fldquals = []
|
||||
for name, type, bitsize, quals in self.enumfields():
|
||||
names.append(name)
|
||||
types.append(type)
|
||||
bitsizes.append(bitsize)
|
||||
fldquals.append(quals)
|
||||
self.fldnames = tuple(names)
|
||||
self.fldtypes = tuple(types)
|
||||
self.fldbitsize = tuple(bitsizes)
|
||||
self.fldquals = tuple(fldquals)
|
||||
|
||||
def get_cached_btype(self, ffi, finishlist, can_delay=False):
|
||||
BType = StructOrUnionOrEnum.get_cached_btype(self, ffi, finishlist,
|
||||
|
@ -305,12 +398,13 @@ class StructOrUnion(StructOrUnionOrEnum):
|
|||
"for '%s'" % (self.name,))
|
||||
return
|
||||
BType = ffi._cached_btypes[self]
|
||||
if self.fldtypes is None:
|
||||
return # not completing it: it's an opaque struct
|
||||
#
|
||||
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)
|
||||
for tp in self.fldtypes]
|
||||
lst = list(zip(self.fldnames, fldtypes, self.fldbitsize))
|
||||
|
@ -449,11 +543,12 @@ def unknown_type(name, structname=None):
|
|||
structname = '$%s' % name
|
||||
tp = StructType(structname, None, None, None)
|
||||
tp.force_the_name(name)
|
||||
tp.origin = "unknown_type"
|
||||
return tp
|
||||
|
||||
def unknown_ptr_type(name, structname=None):
|
||||
if structname is None:
|
||||
structname = '*$%s' % name
|
||||
structname = '$$%s' % name
|
||||
tp = StructType(structname, None, None, None)
|
||||
return NamedPointerType(tp, name)
|
||||
|
||||
|
@ -478,7 +573,7 @@ def global_cache(srctype, ffi, funcname, *args, **kwds):
|
|||
try:
|
||||
res = getattr(ffi._backend, funcname)(*args)
|
||||
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
|
||||
# and contains a rare bug (http://bugs.python.org/issue19542);
|
||||
# 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 head of these two chained lists, as a string that gives the
|
||||
# call to do, if any.
|
||||
self._chained_list_constants = ['0', '0']
|
||||
self._chained_list_constants = ['((void)lib,0)', '((void)lib,0)']
|
||||
#
|
||||
prnt = self._prnt
|
||||
# first paste some standard set of lines that are mostly '#define'
|
||||
|
@ -138,15 +138,26 @@ class VCPythonEngine(object):
|
|||
prnt()
|
||||
prnt('#endif')
|
||||
|
||||
def load_library(self):
|
||||
def load_library(self, flags=None):
|
||||
# XXX review all usages of 'self' here!
|
||||
# import it as a new extension module
|
||||
imp.acquire_lock()
|
||||
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(),
|
||||
self.verifier.modulefilename)
|
||||
except ImportError as e:
|
||||
error = "importing %r: %s" % (self.verifier.modulefilename, e)
|
||||
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
|
||||
# the C compiler
|
||||
|
@ -186,7 +197,10 @@ class VCPythonEngine(object):
|
|||
return library
|
||||
|
||||
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):
|
||||
for name, tp in self._get_declarations():
|
||||
|
@ -228,7 +242,8 @@ class VCPythonEngine(object):
|
|||
converter = '_cffi_to_c_int'
|
||||
extraarg = ', %s' % tp.name
|
||||
else:
|
||||
converter = '_cffi_to_c_%s' % (tp.name.replace(' ', '_'),)
|
||||
converter = '(%s)_cffi_to_c_%s' % (tp.get_c_name(''),
|
||||
tp.name.replace(' ', '_'))
|
||||
errvalue = '-1'
|
||||
#
|
||||
elif isinstance(tp, model.PointerType):
|
||||
|
@ -267,8 +282,8 @@ class VCPythonEngine(object):
|
|||
self._prnt(' if (datasize != 0) {')
|
||||
self._prnt(' if (datasize < 0)')
|
||||
self._prnt(' %s;' % errcode)
|
||||
self._prnt(' %s = alloca(datasize);' % (tovar,))
|
||||
self._prnt(' memset((void *)%s, 0, datasize);' % (tovar,))
|
||||
self._prnt(' %s = alloca((size_t)datasize);' % (tovar,))
|
||||
self._prnt(' memset((void *)%s, 0, (size_t)datasize);' % (tovar,))
|
||||
self._prnt(' if (_cffi_convert_array_from_object('
|
||||
'(char *)%s, _cffi_type(%d), %s) < 0)' % (
|
||||
tovar, self._gettypenum(tp), fromvar))
|
||||
|
@ -336,7 +351,7 @@ class VCPythonEngine(object):
|
|||
prnt = self._prnt
|
||||
numargs = len(tp.args)
|
||||
if numargs == 0:
|
||||
argname = 'no_arg'
|
||||
argname = 'noarg'
|
||||
elif numargs == 1:
|
||||
argname = 'arg0'
|
||||
else:
|
||||
|
@ -386,6 +401,9 @@ class VCPythonEngine(object):
|
|||
prnt(' Py_END_ALLOW_THREADS')
|
||||
prnt()
|
||||
#
|
||||
prnt(' (void)self; /* unused */')
|
||||
if numargs == 0:
|
||||
prnt(' (void)noarg; /* unused */')
|
||||
if result_code:
|
||||
prnt(' return %s;' %
|
||||
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('{')
|
||||
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)
|
||||
and ftype.is_integer_type()) or fbitsize >= 0:
|
||||
# accept all integers, but complain on float or double
|
||||
|
@ -461,7 +480,8 @@ class VCPythonEngine(object):
|
|||
# only accept exactly the type declared.
|
||||
try:
|
||||
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:
|
||||
prnt(' /* %s */' % str(e)) # cannot verify it, ignore
|
||||
prnt('}')
|
||||
|
@ -472,7 +492,7 @@ class VCPythonEngine(object):
|
|||
prnt(' static Py_ssize_t nums[] = {')
|
||||
prnt(' sizeof(%s),' % cname)
|
||||
prnt(' offsetof(struct _cffi_aligncheck, y),')
|
||||
for fname, ftype, fbitsize in tp.enumfields():
|
||||
for fname, ftype, fbitsize, fqual in tp.enumfields():
|
||||
if fbitsize >= 0:
|
||||
continue # xxx ignore fbitsize for now
|
||||
prnt(' offsetof(%s, %s),' % (cname, fname))
|
||||
|
@ -482,6 +502,8 @@ class VCPythonEngine(object):
|
|||
prnt(' sizeof(((%s *)0)->%s),' % (cname, fname))
|
||||
prnt(' -1')
|
||||
prnt(' };')
|
||||
prnt(' (void)self; /* unused */')
|
||||
prnt(' (void)noarg; /* unused */')
|
||||
prnt(' return _cffi_get_struct_layout(nums);')
|
||||
prnt(' /* the next line is not executed, but compiled */')
|
||||
prnt(' %s(0);' % (checkfuncname,))
|
||||
|
@ -534,7 +556,7 @@ class VCPythonEngine(object):
|
|||
check(layout[0], ffi.sizeof(BStruct), "wrong total size")
|
||||
check(layout[1], ffi.alignof(BStruct), "wrong total alignment")
|
||||
i = 2
|
||||
for fname, ftype, fbitsize in tp.enumfields():
|
||||
for fname, ftype, fbitsize, fqual in tp.enumfields():
|
||||
if fbitsize >= 0:
|
||||
continue # xxx ignore fbitsize for now
|
||||
check(layout[i], ffi.offsetof(BStruct, fname),
|
||||
|
@ -578,7 +600,8 @@ class VCPythonEngine(object):
|
|||
# constants, likely declared with '#define'
|
||||
|
||||
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
|
||||
funcname = '_cffi_%s_%s' % (category, name)
|
||||
prnt('static int %s(PyObject *lib)' % funcname)
|
||||
|
@ -590,6 +613,9 @@ class VCPythonEngine(object):
|
|||
else:
|
||||
assert category == 'const'
|
||||
#
|
||||
if check_value is not None:
|
||||
self._check_int_constant_value(name, check_value)
|
||||
#
|
||||
if not is_int:
|
||||
if category == 'var':
|
||||
realexpr = '&' + name
|
||||
|
@ -637,6 +663,27 @@ class VCPythonEngine(object):
|
|||
# ----------
|
||||
# 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):
|
||||
# "$enum_$1" => "___D_enum____D_1"
|
||||
name = name.replace('$', '___D_')
|
||||
|
@ -653,25 +700,8 @@ class VCPythonEngine(object):
|
|||
prnt('static int %s(PyObject *lib)' % funcname)
|
||||
prnt('{')
|
||||
for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues):
|
||||
if enumvalue < 0:
|
||||
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(' 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(' }')
|
||||
self._check_int_constant_value(enumerator, enumvalue,
|
||||
"enum %s: " % name)
|
||||
prnt(' return %s;' % self._chained_list_constants[True])
|
||||
self._chained_list_constants[True] = funcname + '(lib)'
|
||||
prnt('}')
|
||||
|
@ -695,8 +725,11 @@ class VCPythonEngine(object):
|
|||
# macros: for now only for integers
|
||||
|
||||
def _generate_cpy_macro_decl(self, tp, name):
|
||||
assert tp == '...'
|
||||
self._generate_cpy_const(True, name)
|
||||
if tp == '...':
|
||||
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_method = _generate_nothing
|
||||
|
@ -783,6 +816,24 @@ cffimod_header = r'''
|
|||
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
|
||||
|
@ -829,14 +880,18 @@ cffimod_header = r'''
|
|||
|
||||
#define _cffi_from_c_int(x, type) \
|
||||
(((type)-1) > 0 ? /* unsigned */ \
|
||||
(sizeof(type) < sizeof(long) ? PyInt_FromLong(x) : \
|
||||
sizeof(type) == sizeof(long) ? PyLong_FromUnsignedLong(x) : \
|
||||
PyLong_FromUnsignedLongLong(x)) \
|
||||
: (sizeof(type) <= sizeof(long) ? PyInt_FromLong(x) : \
|
||||
PyLong_FromLongLong(x)))
|
||||
(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) \
|
||||
(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)) : \
|
||||
sizeof(type) == 2 ? (((type)-1) > 0 ? (type)_cffi_to_c_u16(o) \
|
||||
: (type)_cffi_to_c_i16(o)) : \
|
||||
|
@ -844,7 +899,7 @@ cffimod_header = r'''
|
|||
: (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), 0))
|
||||
(Py_FatalError("unsupported size for type " #type), (type)0)))
|
||||
|
||||
#define _cffi_to_c_i8 \
|
||||
((int(*)(PyObject *))_cffi_exports[1])
|
||||
|
@ -907,6 +962,7 @@ static PyObject *_cffi_setup(PyObject *self, PyObject *args)
|
|||
{
|
||||
PyObject *library;
|
||||
int was_alive = (_cffi_types != NULL);
|
||||
(void)self; /* unused */
|
||||
if (!PyArg_ParseTuple(args, "OOO", &_cffi_types, &_cffi_VerificationError,
|
||||
&library))
|
||||
return NULL;
|
||||
|
|
|
@ -58,12 +58,12 @@ class VGenericEngine(object):
|
|||
modname = self.verifier.get_module_name()
|
||||
prnt("void %s%s(void) { }\n" % (prefix, modname))
|
||||
|
||||
def load_library(self):
|
||||
def load_library(self, flags=0):
|
||||
# import it with the CFFI backend
|
||||
backend = self.ffi._backend
|
||||
# needs to make a path that contains '/', on Posix
|
||||
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
|
||||
# the C compiler
|
||||
|
@ -87,7 +87,10 @@ class VGenericEngine(object):
|
|||
return library
|
||||
|
||||
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):
|
||||
for name, tp in self._get_declarations():
|
||||
|
@ -149,15 +152,25 @@ class VGenericEngine(object):
|
|||
context = 'argument of %s' % name
|
||||
arglist = [type.get_c_name(' %s' % arg, context)
|
||||
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'
|
||||
wrappername = '_cffi_f_%s' % name
|
||||
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
|
||||
prnt(tp.result.get_c_name(funcdecl, context))
|
||||
prnt(tpresult.get_c_name(funcdecl, context))
|
||||
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 '
|
||||
else:
|
||||
result_code = ''
|
||||
|
@ -174,15 +187,26 @@ class VGenericEngine(object):
|
|||
else:
|
||||
indirections = []
|
||||
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 = []
|
||||
for i, typ in enumerate(tp.args):
|
||||
if isinstance(typ, model.StructOrUnion):
|
||||
typ = model.PointerType(typ)
|
||||
indirections.append((i, 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.result, tp.ellipsis)
|
||||
indirect_result, tp.ellipsis)
|
||||
BFunc = self.ffi._get_cached_btype(tp)
|
||||
wrappername = '_cffi_f_%s' % name
|
||||
newfunction = module.load_function(BFunc, wrappername)
|
||||
|
@ -195,6 +219,13 @@ class VGenericEngine(object):
|
|||
def _make_struct_wrapper(self, oldfunc, i, tp, base_tp):
|
||||
backend = self.ffi._backend
|
||||
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):
|
||||
args = args[:i] + (backend.newp(BType, args[i]),) + args[i+1:]
|
||||
return oldfunc(*args)
|
||||
|
@ -235,7 +266,8 @@ class VGenericEngine(object):
|
|||
prnt('static void %s(%s *p)' % (checkfuncname, cname))
|
||||
prnt('{')
|
||||
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)
|
||||
and ftype.is_integer_type()) or fbitsize >= 0:
|
||||
# accept all integers, but complain on float or double
|
||||
|
@ -244,7 +276,8 @@ class VGenericEngine(object):
|
|||
# only accept exactly the type declared.
|
||||
try:
|
||||
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:
|
||||
prnt(' /* %s */' % str(e)) # cannot verify it, ignore
|
||||
prnt('}')
|
||||
|
@ -255,7 +288,7 @@ class VGenericEngine(object):
|
|||
prnt(' static intptr_t nums[] = {')
|
||||
prnt(' sizeof(%s),' % cname)
|
||||
prnt(' offsetof(struct _cffi_aligncheck, y),')
|
||||
for fname, ftype, fbitsize in tp.enumfields():
|
||||
for fname, ftype, fbitsize, fqual in tp.enumfields():
|
||||
if fbitsize >= 0:
|
||||
continue # xxx ignore fbitsize for now
|
||||
prnt(' offsetof(%s, %s),' % (cname, fname))
|
||||
|
@ -317,7 +350,7 @@ class VGenericEngine(object):
|
|||
check(layout[0], ffi.sizeof(BStruct), "wrong total size")
|
||||
check(layout[1], ffi.alignof(BStruct), "wrong total alignment")
|
||||
i = 2
|
||||
for fname, ftype, fbitsize in tp.enumfields():
|
||||
for fname, ftype, fbitsize, fqual in tp.enumfields():
|
||||
if fbitsize >= 0:
|
||||
continue # xxx ignore fbitsize for now
|
||||
check(layout[i], ffi.offsetof(BStruct, fname),
|
||||
|
@ -354,11 +387,20 @@ class VGenericEngine(object):
|
|||
# ----------
|
||||
# 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
|
||||
funcname = '_cffi_%s_%s' % (category, name)
|
||||
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'
|
||||
prnt('int %s(long long *out_value)' % funcname)
|
||||
prnt('{')
|
||||
|
@ -367,12 +409,17 @@ class VGenericEngine(object):
|
|||
prnt('}')
|
||||
else:
|
||||
assert tp is not None
|
||||
prnt(tp.get_c_name(' %s(void)' % funcname, name),)
|
||||
prnt('{')
|
||||
assert check_value is None
|
||||
if category == 'var':
|
||||
ampersand = '&'
|
||||
else:
|
||||
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('}')
|
||||
prnt()
|
||||
|
@ -383,9 +430,13 @@ class VGenericEngine(object):
|
|||
|
||||
_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
|
||||
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]
|
||||
BFunc = self.ffi._typeof_locked("int(*)(long long*)")[0]
|
||||
function = module.load_function(BFunc, funcname)
|
||||
|
@ -396,9 +447,15 @@ class VGenericEngine(object):
|
|||
BLongLong = self.ffi._typeof_locked("long long")[0]
|
||||
value += (1 << (8*self.ffi.sizeof(BLongLong)))
|
||||
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)
|
||||
value = function()
|
||||
if isinstance(tp, model.StructOrUnion):
|
||||
value = value[0]
|
||||
return value
|
||||
|
||||
def _loaded_gen_constant(self, tp, name, module, library):
|
||||
|
@ -410,6 +467,36 @@ class VGenericEngine(object):
|
|||
# ----------
|
||||
# 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):
|
||||
# "$enum_$1" => "___D_enum____D_1"
|
||||
name = name.replace('$', '___D_')
|
||||
|
@ -427,24 +514,7 @@ class VGenericEngine(object):
|
|||
prnt('int %s(char *out_error)' % funcname)
|
||||
prnt('{')
|
||||
for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues):
|
||||
if enumvalue < 0:
|
||||
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(' }')
|
||||
self._check_int_constant_value(enumerator, enumvalue)
|
||||
prnt(' return 0;')
|
||||
prnt('}')
|
||||
prnt()
|
||||
|
@ -456,16 +526,8 @@ class VGenericEngine(object):
|
|||
tp.enumvalues = tuple(enumvalues)
|
||||
tp.partial_resolved = True
|
||||
else:
|
||||
BType = self.ffi._typeof_locked("char[]")[0]
|
||||
BFunc = self.ffi._typeof_locked("int(*)(char*)")[0]
|
||||
funcname = self._enum_funcname(prefix, name)
|
||||
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)
|
||||
self._load_known_int_constant(module, funcname)
|
||||
|
||||
def _loaded_gen_enum(self, tp, name, module, library):
|
||||
for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues):
|
||||
|
@ -476,13 +538,21 @@ class VGenericEngine(object):
|
|||
# macros: for now only for integers
|
||||
|
||||
def _generate_gen_macro_decl(self, tp, name):
|
||||
assert tp == '...'
|
||||
self._generate_gen_const(True, name)
|
||||
if tp == '...':
|
||||
check_value = None
|
||||
else:
|
||||
check_value = tp # an integer
|
||||
self._generate_gen_const(True, name, check_value=check_value)
|
||||
|
||||
_loading_gen_macro = _loaded_noop
|
||||
|
||||
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)
|
||||
type(library)._cffi_dir.append(name)
|
||||
|
||||
|
@ -565,6 +635,24 @@ cffimod_header = r'''
|
|||
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
|
||||
|
|
|
@ -1,12 +1,47 @@
|
|||
import sys, os, binascii, imp, shutil
|
||||
from . import __version__
|
||||
import sys, os, binascii, shutil, io
|
||||
from . import __version_verifier_modules__
|
||||
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):
|
||||
|
||||
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.preamble = preamble
|
||||
if not modulename:
|
||||
|
@ -14,14 +49,15 @@ class Verifier(object):
|
|||
vengine_class = _locate_engine_class(ffi, force_generic_engine)
|
||||
self._vengine = vengine_class(self)
|
||||
self._vengine.patch_extension_kwds(kwds)
|
||||
self.kwds = kwds
|
||||
self.flags = flags
|
||||
self.kwds = self.make_relative_to(kwds, relative_to)
|
||||
#
|
||||
if modulename:
|
||||
if tag:
|
||||
raise TypeError("can't specify both 'modulename' and 'tag'")
|
||||
else:
|
||||
key = '\x00'.join([sys.version[:3], __version__, preamble,
|
||||
flattened_kwds] +
|
||||
key = '\x00'.join([sys.version[:3], __version_verifier_modules__,
|
||||
preamble, flattened_kwds] +
|
||||
ffi._cdefsources)
|
||||
if sys.version_info >= (3,):
|
||||
key = key.encode('utf-8')
|
||||
|
@ -33,7 +69,7 @@ class Verifier(object):
|
|||
k1, k2)
|
||||
suffix = _get_so_suffixes()[0]
|
||||
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.ext_package = ext_package
|
||||
self._has_source = False
|
||||
|
@ -86,6 +122,7 @@ class Verifier(object):
|
|||
return basename
|
||||
|
||||
def get_extension(self):
|
||||
_hack_at_distutils() # backward compatibility hack
|
||||
if not self._has_source:
|
||||
with self.ffi._lock:
|
||||
if not self._has_source:
|
||||
|
@ -97,6 +134,20 @@ class Verifier(object):
|
|||
def generates_python_module(self):
|
||||
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):
|
||||
|
@ -118,19 +169,36 @@ class Verifier(object):
|
|||
self._vengine.collect_types()
|
||||
self._has_module = True
|
||||
|
||||
def _write_source(self, file=None):
|
||||
must_close = (file is None)
|
||||
if must_close:
|
||||
_ensure_dir(self.sourcefilename)
|
||||
file = open(self.sourcefilename, 'w')
|
||||
def _write_source_to(self, file):
|
||||
self._vengine._f = file
|
||||
try:
|
||||
self._vengine.write_source_to_f()
|
||||
finally:
|
||||
del self._vengine._f
|
||||
if must_close:
|
||||
file.close()
|
||||
if must_close:
|
||||
|
||||
def _write_source(self, file=None):
|
||||
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
|
||||
|
||||
def _compile_module(self):
|
||||
|
@ -148,6 +216,9 @@ class Verifier(object):
|
|||
|
||||
def _load_library(self):
|
||||
assert self._has_module
|
||||
if self.flags is not None:
|
||||
return self._vengine.load_library(self.flags)
|
||||
else:
|
||||
return self._vengine.load_library()
|
||||
|
||||
# ____________________________________________________________
|
||||
|
@ -181,6 +252,9 @@ _TMPDIR = None
|
|||
def _caller_dir_pycache():
|
||||
if _TMPDIR:
|
||||
return _TMPDIR
|
||||
result = os.environ.get('CFFI_TMPDIR')
|
||||
if result:
|
||||
return result
|
||||
filename = sys._getframe(2).f_code.co_filename
|
||||
return os.path.abspath(os.path.join(os.path.dirname(filename),
|
||||
'__pycache__'))
|
||||
|
@ -222,11 +296,7 @@ def cleanup_tmpdir(tmpdir=None, keep_so=False):
|
|||
pass
|
||||
|
||||
def _get_so_suffixes():
|
||||
suffixes = []
|
||||
for suffix, mode, type in imp.get_suffixes():
|
||||
if type == imp.C_EXTENSION:
|
||||
suffixes.append(suffix)
|
||||
|
||||
suffixes = _extension_suffixes()
|
||||
if not suffixes:
|
||||
# bah, no C_EXTENSION available. Occurs on pypy without cpyext
|
||||
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
|
||||
Name: cryptography
|
||||
Version: 0.6
|
||||
Version: 1.1
|
||||
Summary: cryptography is a package which provides cryptographic recipes and primitives to Python developers.
|
||||
Home-page: https://github.com/pyca/cryptography
|
||||
Author: The cryptography developers
|
||||
Author-email: cryptography-dev@python.org
|
||||
License: Apache License, Version 2.0
|
||||
License: BSD or Apache License, Version 2.0
|
||||
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/
|
||||
:alt: Latest Version
|
||||
|
||||
|
@ -20,13 +20,13 @@ Description: Cryptography
|
|||
.. image:: https://travis-ci.org/pyca/cryptography.svg?branch=master
|
||||
:target: https://travis-ci.org/pyca/cryptography
|
||||
|
||||
.. image:: https://coveralls.io/repos/pyca/cryptography/badge.png?branch=master
|
||||
:target: https://coveralls.io/r/pyca/cryptography?branch=master
|
||||
.. image:: https://codecov.io/github/pyca/cryptography/coverage.svg?branch=master
|
||||
:target: https://codecov.io/github/pyca/cryptography?branch=master
|
||||
|
||||
|
||||
``cryptography`` is a package which provides cryptographic recipes and
|
||||
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
|
||||
common cryptographic algorithms such as symmetric ciphers, message digests and
|
||||
|
@ -65,6 +65,7 @@ Description: Cryptography
|
|||
Platform: UNKNOWN
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: License :: OSI Approved :: Apache Software License
|
||||
Classifier: License :: OSI Approved :: BSD License
|
||||
Classifier: Natural Language :: English
|
||||
Classifier: Operating System :: MacOS :: MacOS X
|
||||
Classifier: Operating System :: POSIX
|
||||
|
@ -76,9 +77,9 @@ Classifier: Programming Language :: Python :: 2
|
|||
Classifier: Programming Language :: Python :: 2.6
|
||||
Classifier: Programming Language :: Python :: 2.7
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
Classifier: Programming Language :: Python :: 3.2
|
||||
Classifier: Programming Language :: Python :: 3.3
|
||||
Classifier: Programming Language :: Python :: 3.4
|
||||
Classifier: Programming Language :: Python :: 3.5
|
||||
Classifier: Programming Language :: Python :: Implementation :: CPython
|
||||
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
||||
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/__init__.py
|
||||
../cryptography/exceptions.py
|
||||
../cryptography/fernet.py
|
||||
../cryptography/utils.py
|
||||
../cryptography/hazmat/__init__.py
|
||||
../cryptography/hazmat/bindings/utils.py
|
||||
../cryptography/hazmat/bindings/__init__.py
|
||||
../cryptography/hazmat/primitives/interfaces.py
|
||||
../cryptography/hazmat/primitives/constant_time.py
|
||||
../cryptography/hazmat/primitives/__init__.py
|
||||
../cryptography/hazmat/primitives/hashes.py
|
||||
../cryptography/hazmat/primitives/hmac.py
|
||||
../cryptography/hazmat/primitives/padding.py
|
||||
../cryptography/hazmat/primitives/serialization.py
|
||||
../cryptography/hazmat/primitives/cmac.py
|
||||
../cryptography/x509/__init__.py
|
||||
../cryptography/x509/base.py
|
||||
../cryptography/x509/extensions.py
|
||||
../cryptography/x509/general_name.py
|
||||
../cryptography/x509/name.py
|
||||
../cryptography/x509/oid.py
|
||||
../cryptography/hazmat/backends/__init__.py
|
||||
../cryptography/hazmat/backends/interfaces.py
|
||||
../cryptography/hazmat/backends/multibackend.py
|
||||
../cryptography/hazmat/backends/__init__.py
|
||||
../cryptography/hazmat/bindings/commoncrypto/secimport.py
|
||||
../cryptography/hazmat/bindings/commoncrypto/common_cryptor.py
|
||||
../cryptography/hazmat/bindings/commoncrypto/seckeychain.py
|
||||
../cryptography/hazmat/bindings/commoncrypto/common_hmac.py
|
||||
../cryptography/hazmat/bindings/commoncrypto/__init__.py
|
||||
../cryptography/hazmat/bindings/commoncrypto/common_key_derivation.py
|
||||
../cryptography/hazmat/bindings/commoncrypto/sectransform.py
|
||||
../cryptography/hazmat/bindings/commoncrypto/binding.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/bindings/__init__.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/keywrap.py
|
||||
../cryptography/hazmat/primitives/padding.py
|
||||
../cryptography/hazmat/primitives/serialization.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/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/hashes.py
|
||||
../cryptography/hazmat/backends/openssl/rsa.py
|
||||
../cryptography/hazmat/backends/openssl/hmac.py
|
||||
../cryptography/hazmat/backends/openssl/cmac.py
|
||||
../cryptography/hazmat/backends/openssl/backend.py
|
||||
../cryptography/hazmat/backends/openssl/ciphers.py
|
||||
../cryptography/hazmat/bindings/__pycache__/_Cryptography_cffi_3e31f141x4000d087.c
|
||||
../cryptography/hazmat/primitives/__pycache__/_Cryptography_cffi_7ab3712bx4f158fee.c
|
||||
../cryptography/hazmat/primitives/__pycache__/_Cryptography_cffi_dd416c1exc1767c5a.c
|
||||
../cryptography/hazmat/primitives/src/constant_time.c
|
||||
../cryptography/hazmat/primitives/src/constant_time.h
|
||||
../cryptography/__pycache__/utils.cpython-34.pyc
|
||||
../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/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__/__init__.cpython-34.pyc
|
||||
../cryptography/__pycache__/exceptions.cpython-34.pyc
|
||||
../cryptography/__pycache__/fernet.cpython-34.pyc
|
||||
../cryptography/__pycache__/utils.cpython-34.pyc
|
||||
../cryptography/hazmat/__pycache__/__init__.cpython-34.pyc
|
||||
../cryptography/hazmat/bindings/__pycache__/utils.cpython-34.pyc
|
||||
../cryptography/hazmat/bindings/__pycache__/__init__.cpython-34.pyc
|
||||
../cryptography/hazmat/primitives/__pycache__/interfaces.cpython-34.pyc
|
||||
../cryptography/hazmat/primitives/__pycache__/constant_time.cpython-34.pyc
|
||||
../cryptography/hazmat/primitives/__pycache__/__init__.cpython-34.pyc
|
||||
../cryptography/hazmat/primitives/__pycache__/hashes.cpython-34.pyc
|
||||
../cryptography/hazmat/primitives/__pycache__/hmac.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/x509/__pycache__/__init__.cpython-34.pyc
|
||||
../cryptography/x509/__pycache__/base.cpython-34.pyc
|
||||
../cryptography/x509/__pycache__/extensions.cpython-34.pyc
|
||||
../cryptography/x509/__pycache__/general_name.cpython-34.pyc
|
||||
../cryptography/x509/__pycache__/name.cpython-34.pyc
|
||||
../cryptography/x509/__pycache__/oid.cpython-34.pyc
|
||||
../cryptography/hazmat/backends/__pycache__/__init__.cpython-34.pyc
|
||||
../cryptography/hazmat/backends/__pycache__/interfaces.cpython-34.pyc
|
||||
../cryptography/hazmat/backends/__pycache__/multibackend.cpython-34.pyc
|
||||
../cryptography/hazmat/backends/__pycache__/__init__.cpython-34.pyc
|
||||
../cryptography/hazmat/bindings/commoncrypto/__pycache__/secimport.cpython-34.pyc
|
||||
../cryptography/hazmat/bindings/commoncrypto/__pycache__/common_cryptor.cpython-34.pyc
|
||||
../cryptography/hazmat/bindings/commoncrypto/__pycache__/seckeychain.cpython-34.pyc
|
||||
../cryptography/hazmat/bindings/commoncrypto/__pycache__/common_hmac.cpython-34.pyc
|
||||
../cryptography/hazmat/bindings/commoncrypto/__pycache__/__init__.cpython-34.pyc
|
||||
../cryptography/hazmat/bindings/commoncrypto/__pycache__/common_key_derivation.cpython-34.pyc
|
||||
../cryptography/hazmat/bindings/commoncrypto/__pycache__/sectransform.cpython-34.pyc
|
||||
../cryptography/hazmat/bindings/commoncrypto/__pycache__/binding.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/bindings/__pycache__/__init__.cpython-34.pyc
|
||||
../cryptography/hazmat/primitives/__pycache__/__init__.cpython-34.pyc
|
||||
../cryptography/hazmat/primitives/__pycache__/cmac.cpython-34.pyc
|
||||
../cryptography/hazmat/primitives/__pycache__/constant_time.cpython-34.pyc
|
||||
../cryptography/hazmat/primitives/__pycache__/hashes.cpython-34.pyc
|
||||
../cryptography/hazmat/primitives/__pycache__/hmac.cpython-34.pyc
|
||||
../cryptography/hazmat/primitives/__pycache__/keywrap.cpython-34.pyc
|
||||
../cryptography/hazmat/primitives/__pycache__/padding.cpython-34.pyc
|
||||
../cryptography/hazmat/primitives/__pycache__/serialization.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__/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__/hashes.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__/backend.cpython-34.pyc
|
||||
../cryptography/hazmat/backends/openssl/__pycache__/ciphers.cpython-34.pyc
|
||||
../cryptography/_Cryptography_cffi_3e31f141x4000d087.cpython-34m.so
|
||||
../cryptography/_Cryptography_cffi_7ab3712bx4f158fee.cpython-34m.so
|
||||
../cryptography/_Cryptography_cffi_dd416c1exc1767c5a.cpython-34m.so
|
||||
../cryptography/hazmat/backends/openssl/__pycache__/cmac.cpython-34.pyc
|
||||
../cryptography/hazmat/backends/openssl/__pycache__/dsa.cpython-34.pyc
|
||||
../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
|
||||
entry_points.txt
|
||||
PKG-INFO
|
||||
SOURCES.txt
|
||||
not-zip-safe
|
||||
top_level.txt
|
||||
PKG-INFO
|
||||
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");
|
||||
# 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.
|
||||
# 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
|
||||
|
||||
__all__ = [
|
||||
|
@ -22,10 +14,10 @@ __summary__ = ("cryptography is a package which provides cryptographic recipes"
|
|||
" and primitives to Python developers.")
|
||||
__uri__ = "https://github.com/pyca/cryptography"
|
||||
|
||||
__version__ = "0.6"
|
||||
__version__ = "1.1"
|
||||
|
||||
__author__ = "The cryptography developers"
|
||||
__email__ = "cryptography-dev@python.org"
|
||||
|
||||
__license__ = "Apache License, Version 2.0"
|
||||
__copyright__ = "Copyright 2013-2014 {0}".format(__author__)
|
||||
__license__ = "BSD or Apache License, Version 2.0"
|
||||
__copyright__ = "Copyright 2013-2015 {0}".format(__author__)
|
||||
|
|
|
@ -1,18 +1,12 @@
|
|||
# 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.
|
||||
# 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 sys
|
||||
import warnings
|
||||
|
||||
from cryptography.__about__ import (
|
||||
__author__, __copyright__, __email__, __license__, __summary__, __title__,
|
||||
__uri__, __version__
|
||||
|
@ -23,3 +17,10 @@ __all__ = [
|
|||
"__title__", "__summary__", "__uri__", "__version__", "__author__",
|
||||
"__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");
|
||||
# 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.
|
||||
# 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
|
||||
|
||||
from enum import Enum
|
||||
|
||||
class _Reasons(object):
|
||||
BACKEND_MISSING_INTERFACE = object()
|
||||
UNSUPPORTED_HASH = object()
|
||||
UNSUPPORTED_CIPHER = object()
|
||||
UNSUPPORTED_PADDING = object()
|
||||
UNSUPPORTED_MGF = object()
|
||||
UNSUPPORTED_PUBLIC_KEY_ALGORITHM = object()
|
||||
UNSUPPORTED_ELLIPTIC_CURVE = object()
|
||||
UNSUPPORTED_SERIALIZATION = object()
|
||||
from cryptography import utils
|
||||
from cryptography.hazmat.primitives import twofactor
|
||||
|
||||
|
||||
class _Reasons(Enum):
|
||||
BACKEND_MISSING_INTERFACE = 0
|
||||
UNSUPPORTED_HASH = 1
|
||||
UNSUPPORTED_CIPHER = 2
|
||||
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):
|
||||
|
@ -52,12 +50,21 @@ class InvalidSignature(Exception):
|
|||
|
||||
|
||||
class InternalError(Exception):
|
||||
pass
|
||||
def __init__(self, msg, err_code):
|
||||
super(InternalError, self).__init__(msg)
|
||||
self.err_code = err_code
|
||||
|
||||
|
||||
class InvalidKey(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class InvalidToken(Exception):
|
||||
pass
|
||||
InvalidToken = utils.deprecated(
|
||||
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");
|
||||
# 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.
|
||||
# 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
|
||||
|
||||
|
@ -90,7 +81,7 @@ class Fernet(object):
|
|||
except (TypeError, binascii.Error):
|
||||
raise InvalidToken
|
||||
|
||||
if six.indexbytes(data, 0) != 0x80:
|
||||
if not data or six.indexbytes(data, 0) != 0x80:
|
||||
raise InvalidToken
|
||||
|
||||
try:
|
||||
|
@ -127,3 +118,24 @@ class Fernet(object):
|
|||
except ValueError:
|
||||
raise InvalidToken
|
||||
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");
|
||||
# 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.
|
||||
# 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
|
||||
|
|
|
@ -1,15 +1,6 @@
|
|||
# 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.
|
||||
# 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
|
||||
|
||||
|
@ -26,8 +17,13 @@ def _available_backends():
|
|||
|
||||
if _available_backends_list is None:
|
||||
_available_backends_list = [
|
||||
backend.load(require=False)
|
||||
for backend in pkg_resources.iter_entry_points(
|
||||
# setuptools 11.3 deprecated support for the require parameter to
|
||||
# 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"
|
||||
)
|
||||
]
|
||||
|
|
|
@ -1,15 +1,6 @@
|
|||
# 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.
|
||||
# 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
|
||||
|
||||
|
|
|
@ -1,15 +1,6 @@
|
|||
# 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.
|
||||
# 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
|
||||
|
||||
|
@ -236,7 +227,8 @@ class Backend(object):
|
|||
else:
|
||||
raise InternalError(
|
||||
"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):
|
||||
|
|
|
@ -1,15 +1,6 @@
|
|||
# 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.
|
||||
# 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
|
||||
|
||||
|
@ -17,13 +8,14 @@ from cryptography import utils
|
|||
from cryptography.exceptions import (
|
||||
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 (
|
||||
CFB, CFB8, CTR, OFB
|
||||
)
|
||||
|
||||
|
||||
@utils.register_interface(interfaces.CipherContext)
|
||||
@utils.register_interface(ciphers.CipherContext)
|
||||
class _CipherContext(object):
|
||||
def __init__(self, backend, cipher, mode, operation):
|
||||
self._backend = backend
|
||||
|
@ -40,7 +32,7 @@ class _CipherContext(object):
|
|||
# treat RC4 and other stream cipher block sizes).
|
||||
# This bug has been filed as rdar://15589470
|
||||
self._bytes_processed = 0
|
||||
if (isinstance(cipher, interfaces.BlockCipherAlgorithm) and not
|
||||
if (isinstance(cipher, ciphers.BlockCipherAlgorithm) and not
|
||||
isinstance(mode, (OFB, CFB, CFB8, CTR))):
|
||||
self._byte_block_size = cipher.block_size // 8
|
||||
else:
|
||||
|
@ -60,9 +52,9 @@ class _CipherContext(object):
|
|||
ctx = self._backend._ffi.new("CCCryptorRef *")
|
||||
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
|
||||
elif isinstance(mode, interfaces.ModeWithNonce):
|
||||
elif isinstance(mode, modes.ModeWithNonce):
|
||||
iv_nonce = mode.nonce
|
||||
else:
|
||||
iv_nonce = self._backend._ffi.NULL
|
||||
|
@ -110,8 +102,8 @@ class _CipherContext(object):
|
|||
return self._backend._ffi.buffer(buf)[:outlen[0]]
|
||||
|
||||
|
||||
@utils.register_interface(interfaces.AEADCipherContext)
|
||||
@utils.register_interface(interfaces.AEADEncryptionContext)
|
||||
@utils.register_interface(ciphers.AEADCipherContext)
|
||||
@utils.register_interface(ciphers.AEADEncryptionContext)
|
||||
class _GCMCipherContext(object):
|
||||
def __init__(self, backend, cipher, mode, operation):
|
||||
self._backend = backend
|
||||
|
@ -198,6 +190,4 @@ class _GCMCipherContext(object):
|
|||
)
|
||||
self._backend._check_cipher_response(res)
|
||||
|
||||
@property
|
||||
def tag(self):
|
||||
return self._tag
|
||||
tag = utils.read_only_property("_tag")
|
||||
|
|
|
@ -1,27 +1,18 @@
|
|||
# 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.
|
||||
# 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
|
||||
|
||||
from cryptography import utils
|
||||
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):
|
||||
def __init__(self, backend, algorithm, ctx=None):
|
||||
self.algorithm = algorithm
|
||||
self._algorithm = algorithm
|
||||
self._backend = backend
|
||||
|
||||
if ctx is None:
|
||||
|
@ -39,6 +30,8 @@ class _HashContext(object):
|
|||
|
||||
self._ctx = ctx
|
||||
|
||||
algorithm = utils.read_only_property("_algorithm")
|
||||
|
||||
def copy(self):
|
||||
methods = self._backend._hash_mapping[self.algorithm.name]
|
||||
new_ctx = self._backend._ffi.new(methods.ctx)
|
||||
|
|
|
@ -1,27 +1,21 @@
|
|||
# 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.
|
||||
# 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
|
||||
|
||||
from cryptography import utils
|
||||
from cryptography.exceptions import UnsupportedAlgorithm, _Reasons
|
||||
from cryptography.hazmat.primitives import interfaces
|
||||
from cryptography.exceptions import (
|
||||
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):
|
||||
def __init__(self, backend, key, algorithm, ctx=None):
|
||||
self.algorithm = algorithm
|
||||
self._algorithm = algorithm
|
||||
self._backend = backend
|
||||
if ctx is None:
|
||||
ctx = self._backend._ffi.new("CCHmacContext *")
|
||||
|
@ -39,6 +33,8 @@ class _HMACContext(object):
|
|||
self._ctx = ctx
|
||||
self._key = key
|
||||
|
||||
algorithm = utils.read_only_property("_algorithm")
|
||||
|
||||
def copy(self):
|
||||
copied_ctx = self._backend._ffi.new("CCHmacContext *")
|
||||
# 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._backend._lib.CCHmacFinal(self._ctx, 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");
|
||||
# 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.
|
||||
# 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
|
||||
|
||||
|
@ -66,7 +57,7 @@ class HMACBackend(object):
|
|||
@abc.abstractmethod
|
||||
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
|
||||
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.
|
||||
"""
|
||||
|
||||
@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
|
||||
def rsa_padding_supported(self, padding):
|
||||
"""
|
||||
|
@ -191,20 +149,6 @@ class DSABackend(object):
|
|||
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
|
||||
def dsa_hash_supported(self, algorithm):
|
||||
"""
|
||||
|
@ -268,7 +212,13 @@ class EllipticCurveBackend(object):
|
|||
@abc.abstractmethod
|
||||
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)
|
||||
class TraditionalOpenSSLSerializationBackend(object):
|
||||
class DERSerializationBackend(object):
|
||||
@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
|
||||
is encrypted.
|
||||
Loads a private key from DER encoded data. Uses the provided password
|
||||
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)
|
||||
class PKCS8SerializationBackend(object):
|
||||
class X509Backend(object):
|
||||
@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
|
||||
is encrypted.
|
||||
Load an X.509 certificate from PEM encoded data.
|
||||
"""
|
||||
|
||||
@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");
|
||||
# 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.
|
||||
# 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 warnings
|
||||
|
||||
from cryptography import utils
|
||||
from cryptography.exceptions import UnsupportedAlgorithm, _Reasons
|
||||
from cryptography.hazmat.backends.interfaces import (
|
||||
CMACBackend, CipherBackend, DSABackend, EllipticCurveBackend, HMACBackend,
|
||||
HashBackend, PBKDF2HMACBackend, PEMSerializationBackend,
|
||||
PKCS8SerializationBackend, RSABackend,
|
||||
TraditionalOpenSSLSerializationBackend
|
||||
CMACBackend, CipherBackend, DERSerializationBackend, DSABackend,
|
||||
EllipticCurveBackend, HMACBackend, HashBackend, PBKDF2HMACBackend,
|
||||
PEMSerializationBackend, RSABackend, X509Backend
|
||||
)
|
||||
|
||||
|
||||
@utils.register_interface(CMACBackend)
|
||||
@utils.register_interface(CipherBackend)
|
||||
@utils.register_interface(DERSerializationBackend)
|
||||
@utils.register_interface(HashBackend)
|
||||
@utils.register_interface(HMACBackend)
|
||||
@utils.register_interface(PBKDF2HMACBackend)
|
||||
@utils.register_interface(PKCS8SerializationBackend)
|
||||
@utils.register_interface(RSABackend)
|
||||
@utils.register_interface(TraditionalOpenSSLSerializationBackend)
|
||||
@utils.register_interface(DSABackend)
|
||||
@utils.register_interface(EllipticCurveBackend)
|
||||
@utils.register_interface(PEMSerializationBackend)
|
||||
@utils.register_interface(X509Backend)
|
||||
class MultiBackend(object):
|
||||
name = "multibackend"
|
||||
|
||||
|
@ -47,33 +35,33 @@ class MultiBackend(object):
|
|||
if isinstance(b, interface):
|
||||
yield b
|
||||
|
||||
def cipher_supported(self, algorithm, mode):
|
||||
def cipher_supported(self, cipher, mode):
|
||||
return any(
|
||||
b.cipher_supported(algorithm, mode)
|
||||
b.cipher_supported(cipher, mode)
|
||||
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):
|
||||
try:
|
||||
return b.create_symmetric_encryption_ctx(algorithm, mode)
|
||||
return b.create_symmetric_encryption_ctx(cipher, mode)
|
||||
except UnsupportedAlgorithm:
|
||||
pass
|
||||
raise UnsupportedAlgorithm(
|
||||
"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
|
||||
)
|
||||
|
||||
def create_symmetric_decryption_ctx(self, algorithm, mode):
|
||||
def create_symmetric_decryption_ctx(self, cipher, mode):
|
||||
for b in self._filtered_backends(CipherBackend):
|
||||
try:
|
||||
return b.create_symmetric_decryption_ctx(algorithm, mode)
|
||||
return b.create_symmetric_decryption_ctx(cipher, mode)
|
||||
except UnsupportedAlgorithm:
|
||||
pass
|
||||
raise UnsupportedAlgorithm(
|
||||
"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
|
||||
)
|
||||
|
||||
|
@ -148,38 +136,6 @@ class MultiBackend(object):
|
|||
raise UnsupportedAlgorithm("RSA is not supported by the backend.",
|
||||
_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):
|
||||
for b in self._filtered_backends(RSABackend):
|
||||
return b.rsa_padding_supported(padding)
|
||||
|
@ -218,19 +174,6 @@ class MultiBackend(object):
|
|||
raise UnsupportedAlgorithm("DSA is not supported by the backend.",
|
||||
_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):
|
||||
for b in self._filtered_backends(DSABackend):
|
||||
return b.dsa_hash_supported(algorithm)
|
||||
|
@ -255,6 +198,12 @@ class MultiBackend(object):
|
|||
raise UnsupportedAlgorithm("DSA is not supported by the backend.",
|
||||
_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):
|
||||
return any(
|
||||
b.cmac_algorithm_supported(algorithm)
|
||||
|
@ -298,24 +247,6 @@ class MultiBackend(object):
|
|||
_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):
|
||||
for b in self._filtered_backends(EllipticCurveBackend):
|
||||
try:
|
||||
|
@ -328,24 +259,6 @@ class MultiBackend(object):
|
|||
_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):
|
||||
for b in self._filtered_backends(EllipticCurveBackend):
|
||||
try:
|
||||
|
@ -358,6 +271,12 @@ class MultiBackend(object):
|
|||
_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):
|
||||
for b in self._filtered_backends(PEMSerializationBackend):
|
||||
return b.load_pem_private_key(data, password)
|
||||
|
@ -376,22 +295,92 @@ class MultiBackend(object):
|
|||
_Reasons.UNSUPPORTED_SERIALIZATION
|
||||
)
|
||||
|
||||
def load_pkcs8_pem_private_key(self, data, password):
|
||||
for b in self._filtered_backends(PKCS8SerializationBackend):
|
||||
return b.load_pkcs8_pem_private_key(data, password)
|
||||
def load_der_private_key(self, data, password):
|
||||
for b in self._filtered_backends(DERSerializationBackend):
|
||||
return b.load_der_private_key(data, password)
|
||||
|
||||
raise UnsupportedAlgorithm(
|
||||
"This backend does not support this key serialization.",
|
||||
_Reasons.UNSUPPORTED_SERIALIZATION
|
||||
)
|
||||
|
||||
def load_traditional_openssl_pem_private_key(self, data, password):
|
||||
for b in self._filtered_backends(
|
||||
TraditionalOpenSSLSerializationBackend
|
||||
):
|
||||
return b.load_traditional_openssl_pem_private_key(data, password)
|
||||
def load_der_public_key(self, data):
|
||||
for b in self._filtered_backends(DERSerializationBackend):
|
||||
return b.load_der_public_key(data)
|
||||
|
||||
raise UnsupportedAlgorithm(
|
||||
"This backend does not support this key 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");
|
||||
# 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.
|
||||
# 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
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,27 +1,18 @@
|
|||
# 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.
|
||||
# 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
|
||||
|
||||
from cryptography import utils
|
||||
from cryptography.exceptions import InvalidTag, UnsupportedAlgorithm, _Reasons
|
||||
from cryptography.hazmat.primitives import interfaces
|
||||
from cryptography.hazmat.primitives.ciphers.modes import GCM
|
||||
from cryptography.hazmat.primitives import ciphers
|
||||
from cryptography.hazmat.primitives.ciphers import modes
|
||||
|
||||
|
||||
@utils.register_interface(interfaces.CipherContext)
|
||||
@utils.register_interface(interfaces.AEADCipherContext)
|
||||
@utils.register_interface(interfaces.AEADEncryptionContext)
|
||||
@utils.register_interface(ciphers.CipherContext)
|
||||
@utils.register_interface(ciphers.AEADCipherContext)
|
||||
@utils.register_interface(ciphers.AEADEncryptionContext)
|
||||
class _CipherContext(object):
|
||||
_ENCRYPT = 1
|
||||
_DECRYPT = 0
|
||||
|
@ -33,7 +24,7 @@ class _CipherContext(object):
|
|||
self._operation = operation
|
||||
self._tag = None
|
||||
|
||||
if isinstance(self._cipher, interfaces.BlockCipherAlgorithm):
|
||||
if isinstance(self._cipher, ciphers.BlockCipherAlgorithm):
|
||||
self._block_size = self._cipher.block_size
|
||||
else:
|
||||
self._block_size = 1
|
||||
|
@ -63,9 +54,9 @@ class _CipherContext(object):
|
|||
_Reasons.UNSUPPORTED_CIPHER
|
||||
)
|
||||
|
||||
if isinstance(mode, interfaces.ModeWithInitializationVector):
|
||||
if isinstance(mode, modes.ModeWithInitializationVector):
|
||||
iv_nonce = mode.initialization_vector
|
||||
elif isinstance(mode, interfaces.ModeWithNonce):
|
||||
elif isinstance(mode, modes.ModeWithNonce):
|
||||
iv_nonce = mode.nonce
|
||||
else:
|
||||
iv_nonce = self._backend._ffi.NULL
|
||||
|
@ -75,24 +66,24 @@ class _CipherContext(object):
|
|||
self._backend._ffi.NULL,
|
||||
self._backend._ffi.NULL,
|
||||
operation)
|
||||
assert res != 0
|
||||
self._backend.openssl_assert(res != 0)
|
||||
# set the key length to handle variable key ciphers
|
||||
res = self._backend._lib.EVP_CIPHER_CTX_set_key_length(
|
||||
ctx, len(cipher.key)
|
||||
)
|
||||
assert res != 0
|
||||
if isinstance(mode, GCM):
|
||||
self._backend.openssl_assert(res != 0)
|
||||
if isinstance(mode, modes.GCM):
|
||||
res = self._backend._lib.EVP_CIPHER_CTX_ctrl(
|
||||
ctx, self._backend._lib.EVP_CTRL_GCM_SET_IVLEN,
|
||||
len(iv_nonce), self._backend._ffi.NULL
|
||||
)
|
||||
assert res != 0
|
||||
self._backend.openssl_assert(res != 0)
|
||||
if operation == self._DECRYPT:
|
||||
res = self._backend._lib.EVP_CIPHER_CTX_ctrl(
|
||||
ctx, self._backend._lib.EVP_CTRL_GCM_SET_TAG,
|
||||
len(mode.tag), mode.tag
|
||||
)
|
||||
assert res != 0
|
||||
self._backend.openssl_assert(res != 0)
|
||||
|
||||
# pass key/iv
|
||||
res = self._backend._lib.EVP_CipherInit_ex(
|
||||
|
@ -103,7 +94,7 @@ class _CipherContext(object):
|
|||
iv_nonce,
|
||||
operation
|
||||
)
|
||||
assert res != 0
|
||||
self._backend.openssl_assert(res != 0)
|
||||
# We purposely disable padding here as it's handled higher up in the
|
||||
# API.
|
||||
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
|
||||
# AES GCM can return improper tag values if you don't call update
|
||||
# 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""
|
||||
|
||||
buf = self._backend._ffi.new("unsigned char[]",
|
||||
|
@ -124,7 +115,7 @@ class _CipherContext(object):
|
|||
outlen = self._backend._ffi.new("int *")
|
||||
res = self._backend._lib.EVP_CipherUpdate(self._ctx, buf, outlen, data,
|
||||
len(data))
|
||||
assert res != 0
|
||||
self._backend.openssl_assert(res != 0)
|
||||
return self._backend._ffi.buffer(buf)[:outlen[0]]
|
||||
|
||||
def finalize(self):
|
||||
|
@ -133,7 +124,7 @@ class _CipherContext(object):
|
|||
# even if you are only using authenticate_additional_data or the
|
||||
# GCM tag will be wrong. An (empty) call to update resolves this
|
||||
# and is harmless for all other versions of OpenSSL.
|
||||
if isinstance(self._mode, GCM):
|
||||
if isinstance(self._mode, modes.GCM):
|
||||
self.update(b"")
|
||||
|
||||
buf = self._backend._ffi.new("unsigned char[]", self._block_size)
|
||||
|
@ -142,12 +133,11 @@ class _CipherContext(object):
|
|||
if res == 0:
|
||||
errors = self._backend._consume_errors()
|
||||
|
||||
if not errors and isinstance(self._mode, GCM):
|
||||
if not errors and isinstance(self._mode, modes.GCM):
|
||||
raise InvalidTag
|
||||
|
||||
assert errors
|
||||
|
||||
if errors[0][1:] == (
|
||||
self._backend.openssl_assert(
|
||||
errors[0][1:] == (
|
||||
self._backend._lib.ERR_LIB_EVP,
|
||||
self._backend._lib.EVP_F_EVP_ENCRYPTFINAL_EX,
|
||||
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.EVP_F_EVP_DECRYPTFINAL_EX,
|
||||
self._backend._lib.EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH
|
||||
):
|
||||
)
|
||||
)
|
||||
raise ValueError(
|
||||
"The length of the provided data is not a multiple of "
|
||||
"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):
|
||||
block_byte_size = self._block_size // 8
|
||||
tag_buf = self._backend._ffi.new(
|
||||
|
@ -173,11 +162,11 @@ class _CipherContext(object):
|
|||
self._ctx, self._backend._lib.EVP_CTRL_GCM_GET_TAG,
|
||||
block_byte_size, tag_buf
|
||||
)
|
||||
assert res != 0
|
||||
self._backend.openssl_assert(res != 0)
|
||||
self._tag = self._backend._ffi.buffer(tag_buf)[:]
|
||||
|
||||
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]]
|
||||
|
||||
def authenticate_additional_data(self, data):
|
||||
|
@ -185,14 +174,12 @@ class _CipherContext(object):
|
|||
res = self._backend._lib.EVP_CipherUpdate(
|
||||
self._ctx, self._backend._ffi.NULL, outlen, data, len(data)
|
||||
)
|
||||
assert res != 0
|
||||
self._backend.openssl_assert(res != 0)
|
||||
|
||||
@property
|
||||
def tag(self):
|
||||
return self._tag
|
||||
tag = utils.read_only_property("_tag")
|
||||
|
||||
|
||||
@utils.register_interface(interfaces.CipherContext)
|
||||
@utils.register_interface(ciphers.CipherContext)
|
||||
class _AESCTRCipherContext(object):
|
||||
"""
|
||||
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._key = self._backend._ffi.new("AES_KEY *")
|
||||
assert self._key != self._backend._ffi.NULL
|
||||
res = self._backend._lib.AES_set_encrypt_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._nonce = self._backend._ffi.new("char[16]", mode.nonce)
|
||||
self._num = self._backend._ffi.new("unsigned int *", 0)
|
||||
|
|
|
@ -1,26 +1,19 @@
|
|||
# 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.
|
||||
# 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
|
||||
|
||||
|
||||
from cryptography import utils
|
||||
from cryptography.exceptions import UnsupportedAlgorithm, _Reasons
|
||||
from cryptography.hazmat.primitives import interfaces
|
||||
from cryptography.exceptions import (
|
||||
InvalidSignature, UnsupportedAlgorithm, _Reasons
|
||||
)
|
||||
from cryptography.hazmat.primitives import constant_time, interfaces
|
||||
from cryptography.hazmat.primitives.ciphers.modes import CBC
|
||||
|
||||
|
||||
@utils.register_interface(interfaces.CMACContext)
|
||||
@utils.register_interface(interfaces.MACContext)
|
||||
class _CMACContext(object):
|
||||
def __init__(self, backend, algorithm, ctx=None):
|
||||
if not backend.cmac_algorithm_supported(algorithm):
|
||||
|
@ -40,7 +33,7 @@ class _CMACContext(object):
|
|||
|
||||
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)
|
||||
|
||||
self._backend._lib.CMAC_Init(
|
||||
|
@ -50,9 +43,11 @@ class _CMACContext(object):
|
|||
|
||||
self._ctx = ctx
|
||||
|
||||
algorithm = utils.read_only_property("_algorithm")
|
||||
|
||||
def update(self, data):
|
||||
res = self._backend._lib.CMAC_Update(self._ctx, data, len(data))
|
||||
assert res == 1
|
||||
self._backend.openssl_assert(res == 1)
|
||||
|
||||
def finalize(self):
|
||||
buf = self._backend._ffi.new("unsigned char[]", self._output_length)
|
||||
|
@ -60,7 +55,7 @@ class _CMACContext(object):
|
|||
res = self._backend._lib.CMAC_Final(
|
||||
self._ctx, buf, length
|
||||
)
|
||||
assert res == 1
|
||||
self._backend.openssl_assert(res == 1)
|
||||
|
||||
self._ctx = None
|
||||
|
||||
|
@ -74,7 +69,12 @@ class _CMACContext(object):
|
|||
res = self._backend._lib.CMAC_CTX_copy(
|
||||
copied_ctx, self._ctx
|
||||
)
|
||||
assert res == 1
|
||||
self._backend.openssl_assert(res == 1)
|
||||
return _CMACContext(
|
||||
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");
|
||||
# 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.
|
||||
# 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
|
||||
|
||||
from cryptography import utils
|
||||
from cryptography.exceptions import InvalidSignature
|
||||
from cryptography.hazmat.primitives import hashes, interfaces
|
||||
from cryptography.hazmat.primitives.asymmetric import dsa
|
||||
from cryptography.hazmat.primitives.interfaces import (
|
||||
DSAParametersWithNumbers, DSAPrivateKeyWithNumbers, DSAPublicKeyWithNumbers
|
||||
from cryptography.hazmat.backends.openssl.utils import _truncate_digest
|
||||
from cryptography.hazmat.primitives import hashes, serialization
|
||||
from cryptography.hazmat.primitives.asymmetric import (
|
||||
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):
|
||||
def __init__(self, backend, public_key, signature, algorithm):
|
||||
self._backend = backend
|
||||
|
@ -36,11 +40,12 @@ class _DSAVerificationContext(object):
|
|||
self._hash_ctx.update(data)
|
||||
|
||||
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 = _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
|
||||
# must be an integer.
|
||||
res = self._backend._lib.DSA_verify(
|
||||
|
@ -48,15 +53,11 @@ class _DSAVerificationContext(object):
|
|||
len(self._signature), self._public_key._dsa_cdata)
|
||||
|
||||
if res != 1:
|
||||
errors = self._backend._consume_errors()
|
||||
assert errors
|
||||
if res == -1:
|
||||
assert errors[0].lib == self._backend._lib.ERR_LIB_ASN1
|
||||
|
||||
self._backend._consume_errors()
|
||||
raise InvalidSignature
|
||||
|
||||
|
||||
@utils.register_interface(interfaces.AsymmetricSignatureContext)
|
||||
@utils.register_interface(AsymmetricSignatureContext)
|
||||
class _DSASignatureContext(object):
|
||||
def __init__(self, backend, private_key, algorithm):
|
||||
self._backend = backend
|
||||
|
@ -69,6 +70,9 @@ class _DSASignatureContext(object):
|
|||
|
||||
def finalize(self):
|
||||
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 = self._backend._ffi.new("unsigned char[]", sig_buf_len)
|
||||
buflen = self._backend._ffi.new("unsigned int *")
|
||||
|
@ -78,13 +82,13 @@ class _DSASignatureContext(object):
|
|||
res = self._backend._lib.DSA_sign(
|
||||
0, data_to_sign, len(data_to_sign), sig_buf,
|
||||
buflen, self._private_key._dsa_cdata)
|
||||
assert res == 1
|
||||
assert buflen[0]
|
||||
self._backend.openssl_assert(res == 1)
|
||||
self._backend.openssl_assert(buflen[0])
|
||||
|
||||
return self._backend._ffi.buffer(sig_buf)[:buflen[0]]
|
||||
|
||||
|
||||
@utils.register_interface(DSAParametersWithNumbers)
|
||||
@utils.register_interface(dsa.DSAParametersWithNumbers)
|
||||
class _DSAParameters(object):
|
||||
def __init__(self, backend, dsa_cdata):
|
||||
self._backend = backend
|
||||
|
@ -101,19 +105,18 @@ class _DSAParameters(object):
|
|||
return self._backend.generate_dsa_private_key(self)
|
||||
|
||||
|
||||
@utils.register_interface(DSAPrivateKeyWithNumbers)
|
||||
@utils.register_interface(dsa.DSAPrivateKeyWithSerialization)
|
||||
class _DSAPrivateKey(object):
|
||||
def __init__(self, backend, dsa_cdata):
|
||||
def __init__(self, backend, dsa_cdata, evp_pkey):
|
||||
self._backend = backend
|
||||
self._dsa_cdata = dsa_cdata
|
||||
self._evp_pkey = evp_pkey
|
||||
self._key_size = self._backend._lib.BN_num_bits(self._dsa_cdata.p)
|
||||
|
||||
@property
|
||||
def key_size(self):
|
||||
return self._key_size
|
||||
key_size = utils.read_only_property("_key_size")
|
||||
|
||||
def signer(self, algorithm):
|
||||
return _DSASignatureContext(self._backend, self, algorithm)
|
||||
def signer(self, signature_algorithm):
|
||||
return _DSASignatureContext(self._backend, self, signature_algorithm)
|
||||
|
||||
def private_numbers(self):
|
||||
return dsa.DSAPrivateNumbers(
|
||||
|
@ -130,7 +133,7 @@ class _DSAPrivateKey(object):
|
|||
|
||||
def public_key(self):
|
||||
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._lib.DSA_free
|
||||
)
|
||||
|
@ -138,11 +141,12 @@ class _DSAPrivateKey(object):
|
|||
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.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):
|
||||
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._lib.DSA_free
|
||||
)
|
||||
|
@ -151,21 +155,32 @@ class _DSAPrivateKey(object):
|
|||
dsa_cdata.g = self._backend._lib.BN_dup(self._dsa_cdata.g)
|
||||
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):
|
||||
def __init__(self, backend, dsa_cdata):
|
||||
def __init__(self, backend, dsa_cdata, evp_pkey):
|
||||
self._backend = backend
|
||||
self._dsa_cdata = dsa_cdata
|
||||
self._evp_pkey = evp_pkey
|
||||
self._key_size = self._backend._lib.BN_num_bits(self._dsa_cdata.p)
|
||||
|
||||
@property
|
||||
def key_size(self):
|
||||
return self._key_size
|
||||
key_size = utils.read_only_property("_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(
|
||||
self._backend, self, signature, algorithm
|
||||
self._backend, self, signature, signature_algorithm
|
||||
)
|
||||
|
||||
def public_numbers(self):
|
||||
|
@ -180,7 +195,7 @@ class _DSAPublicKey(object):
|
|||
|
||||
def parameters(self):
|
||||
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._lib.DSA_free
|
||||
)
|
||||
|
@ -188,3 +203,16 @@ class _DSAPublicKey(object):
|
|||
dsa_cdata.q = self._backend._lib.BN_dup(self._dsa_cdata.q)
|
||||
dsa_cdata.g = self._backend._lib.BN_dup(self._dsa_cdata.g)
|
||||
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");
|
||||
# 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.
|
||||
# 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
|
||||
|
||||
from cryptography import utils
|
||||
from cryptography.exceptions import (
|
||||
InvalidSignature, UnsupportedAlgorithm, _Reasons
|
||||
)
|
||||
from cryptography.hazmat.primitives import hashes, interfaces
|
||||
from cryptography.hazmat.primitives.asymmetric import ec
|
||||
from cryptography.hazmat.backends.openssl.utils import _truncate_digest
|
||||
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):
|
||||
|
@ -34,49 +26,52 @@ def _truncate_digest_for_ecdsa(ec_key_cdata, digest, backend):
|
|||
_lib = backend._lib
|
||||
_ffi = backend._ffi
|
||||
|
||||
digest_len = len(digest)
|
||||
|
||||
group = _lib.EC_KEY_get0_group(ec_key_cdata)
|
||||
|
||||
with backend._tmp_bn_ctx() as 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)
|
||||
assert res == 1
|
||||
backend.openssl_assert(res == 1)
|
||||
|
||||
order_bits = _lib.BN_num_bits(order)
|
||||
|
||||
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 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
|
||||
return _truncate_digest(digest, order_bits)
|
||||
|
||||
|
||||
def _ec_key_curve_sn(backend, 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)
|
||||
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)
|
||||
assert curve_name != backend._ffi.NULL
|
||||
backend.openssl_assert(curve_name != backend._ffi.NULL)
|
||||
|
||||
sn = backend._ffi.string(curve_name).decode('ascii')
|
||||
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):
|
||||
try:
|
||||
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):
|
||||
def __init__(self, backend, private_key, algorithm):
|
||||
self._backend = backend
|
||||
|
@ -105,7 +100,7 @@ class _ECDSASignatureContext(object):
|
|||
digest = _truncate_digest_for_ecdsa(ec_key, digest, self._backend)
|
||||
|
||||
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)
|
||||
siglen_ptr = self._backend._ffi.new("unsigned int[]", 1)
|
||||
|
@ -117,11 +112,11 @@ class _ECDSASignatureContext(object):
|
|||
siglen_ptr,
|
||||
ec_key
|
||||
)
|
||||
assert res == 1
|
||||
self._backend.openssl_assert(res == 1)
|
||||
return self._backend._ffi.buffer(sigbuf)[:siglen_ptr[0]]
|
||||
|
||||
|
||||
@utils.register_interface(interfaces.AsymmetricVerificationContext)
|
||||
@utils.register_interface(AsymmetricVerificationContext)
|
||||
class _ECDSAVerificationContext(object):
|
||||
def __init__(self, backend, public_key, signature, algorithm):
|
||||
self._backend = backend
|
||||
|
@ -153,18 +148,18 @@ class _ECDSAVerificationContext(object):
|
|||
return True
|
||||
|
||||
|
||||
@utils.register_interface(interfaces.EllipticCurvePrivateKeyWithNumbers)
|
||||
@utils.register_interface(ec.EllipticCurvePrivateKeyWithSerialization)
|
||||
class _EllipticCurvePrivateKey(object):
|
||||
def __init__(self, backend, ec_key_cdata):
|
||||
def __init__(self, backend, ec_key_cdata, evp_pkey):
|
||||
self._backend = backend
|
||||
_mark_asn1_named_ec_curve(backend, ec_key_cdata)
|
||||
self._ec_key = ec_key_cdata
|
||||
self._evp_pkey = evp_pkey
|
||||
|
||||
sn = _ec_key_curve_sn(backend, ec_key_cdata)
|
||||
self._curve = _sn_to_elliptic_curve(backend, sn)
|
||||
|
||||
@property
|
||||
def curve(self):
|
||||
return self._curve
|
||||
curve = utils.read_only_property("_curve")
|
||||
|
||||
def signer(self, signature_algorithm):
|
||||
if isinstance(signature_algorithm, ec.ECDSA):
|
||||
|
@ -176,27 +171,52 @@ class _EllipticCurvePrivateKey(object):
|
|||
"Unsupported elliptic curve signature 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):
|
||||
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)
|
||||
|
||||
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._lib.EC_KEY_free
|
||||
)
|
||||
|
||||
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)
|
||||
assert res == 1
|
||||
self._backend.openssl_assert(res == 1)
|
||||
|
||||
return _EllipticCurvePublicKey(
|
||||
self._backend, public_ec_key
|
||||
)
|
||||
evp_pkey = self._backend._ec_cdata_to_evp_pkey(public_ec_key)
|
||||
|
||||
return _EllipticCurvePublicKey(self._backend, public_ec_key, evp_pkey)
|
||||
|
||||
def private_numbers(self):
|
||||
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()
|
||||
)
|
||||
|
||||
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):
|
||||
def __init__(self, backend, ec_key_cdata):
|
||||
def __init__(self, backend, ec_key_cdata, evp_pkey):
|
||||
self._backend = backend
|
||||
_mark_asn1_named_ec_curve(backend, ec_key_cdata)
|
||||
self._ec_key = ec_key_cdata
|
||||
self._evp_pkey = evp_pkey
|
||||
|
||||
sn = _ec_key_curve_sn(backend, ec_key_cdata)
|
||||
self._curve = _sn_to_elliptic_curve(backend, sn)
|
||||
|
||||
@property
|
||||
def curve(self):
|
||||
return self._curve
|
||||
curve = utils.read_only_property("_curve")
|
||||
|
||||
def verifier(self, signature, signature_algorithm):
|
||||
if not isinstance(signature, bytes):
|
||||
raise TypeError("signature must be bytes.")
|
||||
|
||||
if isinstance(signature_algorithm, ec.ECDSA):
|
||||
return _ECDSAVerificationContext(
|
||||
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)
|
||||
)
|
||||
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:
|
||||
bn_x = 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)
|
||||
assert res == 1
|
||||
self._backend.openssl_assert(res == 1)
|
||||
|
||||
x = self._backend._bn_to_int(bn_x)
|
||||
y = self._backend._bn_to_int(bn_y)
|
||||
|
@ -252,3 +284,16 @@ class _EllipticCurvePublicKey(object):
|
|||
y=y,
|
||||
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");
|
||||
# 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.
|
||||
# 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
|
||||
|
||||
|
||||
from cryptography import utils
|
||||
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):
|
||||
def __init__(self, backend, algorithm, ctx=None):
|
||||
self.algorithm = algorithm
|
||||
self._algorithm = algorithm
|
||||
|
||||
self._backend = backend
|
||||
|
||||
|
@ -40,30 +31,32 @@ class _HashContext(object):
|
|||
)
|
||||
res = self._backend._lib.EVP_DigestInit_ex(ctx, evp_md,
|
||||
self._backend._ffi.NULL)
|
||||
assert res != 0
|
||||
self._backend.openssl_assert(res != 0)
|
||||
|
||||
self._ctx = ctx
|
||||
|
||||
algorithm = utils.read_only_property("_algorithm")
|
||||
|
||||
def copy(self):
|
||||
copied_ctx = self._backend._lib.EVP_MD_CTX_create()
|
||||
copied_ctx = self._backend._ffi.gc(
|
||||
copied_ctx, self._backend._lib.EVP_MD_CTX_destroy
|
||||
)
|
||||
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)
|
||||
|
||||
def update(self, data):
|
||||
res = self._backend._lib.EVP_DigestUpdate(self._ctx, data, len(data))
|
||||
assert res != 0
|
||||
self._backend.openssl_assert(res != 0)
|
||||
|
||||
def finalize(self):
|
||||
buf = self._backend._ffi.new("unsigned char[]",
|
||||
self._backend._lib.EVP_MAX_MD_SIZE)
|
||||
outlen = self._backend._ffi.new("unsigned int *")
|
||||
res = self._backend._lib.EVP_DigestFinal_ex(self._ctx, buf, outlen)
|
||||
assert res != 0
|
||||
assert outlen[0] == self.algorithm.digest_size
|
||||
self._backend.openssl_assert(res != 0)
|
||||
self._backend.openssl_assert(outlen[0] == self.algorithm.digest_size)
|
||||
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]]
|
||||
|
|
|
@ -1,28 +1,22 @@
|
|||
# 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.
|
||||
# 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
|
||||
|
||||
|
||||
from cryptography import utils
|
||||
from cryptography.exceptions import UnsupportedAlgorithm, _Reasons
|
||||
from cryptography.hazmat.primitives import interfaces
|
||||
from cryptography.exceptions import (
|
||||
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):
|
||||
def __init__(self, backend, key, algorithm, ctx=None):
|
||||
self.algorithm = algorithm
|
||||
self._algorithm = algorithm
|
||||
self._backend = backend
|
||||
|
||||
if ctx is None:
|
||||
|
@ -42,11 +36,13 @@ class _HMACContext(object):
|
|||
res = self._backend._lib.Cryptography_HMAC_Init_ex(
|
||||
ctx, key, len(key), evp_md, self._backend._ffi.NULL
|
||||
)
|
||||
assert res != 0
|
||||
self._backend.openssl_assert(res != 0)
|
||||
|
||||
self._ctx = ctx
|
||||
self._key = key
|
||||
|
||||
algorithm = utils.read_only_property("_algorithm")
|
||||
|
||||
def copy(self):
|
||||
copied_ctx = self._backend._ffi.new("HMAC_CTX *")
|
||||
self._backend._lib.HMAC_CTX_init(copied_ctx)
|
||||
|
@ -56,7 +52,7 @@ class _HMACContext(object):
|
|||
res = self._backend._lib.Cryptography_HMAC_CTX_copy(
|
||||
copied_ctx, self._ctx
|
||||
)
|
||||
assert res != 0
|
||||
self._backend.openssl_assert(res != 0)
|
||||
return _HMACContext(
|
||||
self._backend, self._key, self.algorithm, ctx=copied_ctx
|
||||
)
|
||||
|
@ -65,7 +61,7 @@ class _HMACContext(object):
|
|||
res = self._backend._lib.Cryptography_HMAC_Update(
|
||||
self._ctx, data, len(data)
|
||||
)
|
||||
assert res != 0
|
||||
self._backend.openssl_assert(res != 0)
|
||||
|
||||
def finalize(self):
|
||||
buf = self._backend._ffi.new("unsigned char[]",
|
||||
|
@ -74,7 +70,12 @@ class _HMACContext(object):
|
|||
res = self._backend._lib.Cryptography_HMAC_Final(
|
||||
self._ctx, buf, outlen
|
||||
)
|
||||
assert res != 0
|
||||
assert outlen[0] == self.algorithm.digest_size
|
||||
self._backend.openssl_assert(res != 0)
|
||||
self._backend.openssl_assert(outlen[0] == self.algorithm.digest_size)
|
||||
self._backend._lib.HMAC_CTX_cleanup(self._ctx)
|
||||
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");
|
||||
# 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.
|
||||
# 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
|
||||
|
||||
|
@ -19,13 +10,15 @@ from cryptography import utils
|
|||
from cryptography.exceptions import (
|
||||
AlreadyFinalized, InvalidSignature, UnsupportedAlgorithm, _Reasons
|
||||
)
|
||||
from cryptography.hazmat.primitives import hashes, interfaces
|
||||
from cryptography.hazmat.primitives.asymmetric import rsa
|
||||
from cryptography.hazmat.primitives.asymmetric.padding import (
|
||||
MGF1, OAEP, PKCS1v15, PSS
|
||||
from cryptography.hazmat.primitives import hashes
|
||||
from cryptography.hazmat.primitives.asymmetric import (
|
||||
AsymmetricSignatureContext, AsymmetricVerificationContext, rsa
|
||||
)
|
||||
from cryptography.hazmat.primitives.interfaces import (
|
||||
RSAPrivateKeyWithNumbers, RSAPublicKeyWithNumbers
|
||||
from cryptography.hazmat.primitives.asymmetric.padding import (
|
||||
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):
|
||||
if not isinstance(padding, interfaces.AsymmetricPadding):
|
||||
if not isinstance(padding, AsymmetricPadding):
|
||||
raise TypeError("Padding must be an instance of AsymmetricPadding.")
|
||||
|
||||
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(
|
||||
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)
|
||||
res = init(pkey_ctx)
|
||||
assert res == 1
|
||||
backend.openssl_assert(res == 1)
|
||||
res = backend._lib.EVP_PKEY_CTX_set_rsa_padding(
|
||||
pkey_ctx, padding_enum)
|
||||
assert res > 0
|
||||
backend.openssl_assert(res > 0)
|
||||
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)
|
||||
buf = backend._ffi.new("char[]", buf_size)
|
||||
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
|
||||
|
||||
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)
|
||||
res = crypt(len(data), data, buf, key._rsa_cdata, padding_enum)
|
||||
if res < 0:
|
||||
|
@ -142,26 +135,30 @@ def _handle_rsa_enc_dec_error(backend, key):
|
|||
"larger key size."
|
||||
)
|
||||
else:
|
||||
assert (
|
||||
errors[0].reason == backend._lib.RSA_R_BLOCK_TYPE_IS_NOT_01 or
|
||||
errors[0].reason == backend._lib.RSA_R_BLOCK_TYPE_IS_NOT_02
|
||||
)
|
||||
decoding_errors = [
|
||||
backend._lib.RSA_R_BLOCK_TYPE_IS_NOT_01,
|
||||
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.")
|
||||
|
||||
|
||||
@utils.register_interface(interfaces.AsymmetricSignatureContext)
|
||||
@utils.register_interface(AsymmetricSignatureContext)
|
||||
class _RSASignatureContext(object):
|
||||
def __init__(self, backend, private_key, padding, algorithm):
|
||||
self._backend = backend
|
||||
self._private_key = private_key
|
||||
|
||||
if not isinstance(padding, interfaces.AsymmetricPadding):
|
||||
raise TypeError(
|
||||
"Expected provider of interfaces.AsymmetricPadding.")
|
||||
if not isinstance(padding, AsymmetricPadding):
|
||||
raise TypeError("Expected provider of AsymmetricPadding.")
|
||||
|
||||
self._pkey_size = self._backend._lib.EVP_PKEY_size(
|
||||
self._private_key._evp_pkey
|
||||
)
|
||||
self._backend.openssl_assert(self._pkey_size > 0)
|
||||
|
||||
if isinstance(padding, PKCS1v15):
|
||||
if self._backend._lib.Cryptography_HAS_PKEY_CTX:
|
||||
|
@ -178,7 +175,6 @@ class _RSASignatureContext(object):
|
|||
|
||||
# Size of key in bytes - 2 is the maximum
|
||||
# PSS signature length (salt length is checked later)
|
||||
assert self._pkey_size > 0
|
||||
if self._pkey_size - algorithm.digest_size - 2 < 0:
|
||||
raise ValueError("Digest too large for key size. Use a larger "
|
||||
"key.")
|
||||
|
@ -211,7 +207,7 @@ class _RSASignatureContext(object):
|
|||
def finalize(self):
|
||||
evp_md = self._backend._lib.EVP_get_digestbyname(
|
||||
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)
|
||||
|
||||
|
@ -219,18 +215,18 @@ class _RSASignatureContext(object):
|
|||
pkey_ctx = self._backend._lib.EVP_PKEY_CTX_new(
|
||||
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,
|
||||
self._backend._lib.EVP_PKEY_CTX_free)
|
||||
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(
|
||||
pkey_ctx, evp_md)
|
||||
assert res > 0
|
||||
self._backend.openssl_assert(res > 0)
|
||||
|
||||
res = self._backend._lib.EVP_PKEY_CTX_set_rsa_padding(
|
||||
pkey_ctx, self._padding_enum)
|
||||
assert res > 0
|
||||
self._backend.openssl_assert(res > 0)
|
||||
if isinstance(self._padding, PSS):
|
||||
res = self._backend._lib.EVP_PKEY_CTX_set_rsa_pss_saltlen(
|
||||
pkey_ctx,
|
||||
|
@ -240,17 +236,19 @@ class _RSASignatureContext(object):
|
|||
self._hash_ctx.algorithm.digest_size
|
||||
)
|
||||
)
|
||||
assert res > 0
|
||||
self._backend.openssl_assert(res > 0)
|
||||
|
||||
if self._backend._lib.Cryptography_HAS_MGF1_MD:
|
||||
# MGF1 MD is configurable in OpenSSL 1.0.1+
|
||||
mgf1_md = self._backend._lib.EVP_get_digestbyname(
|
||||
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(
|
||||
pkey_ctx, mgf1_md
|
||||
)
|
||||
assert res > 0
|
||||
self._backend.openssl_assert(res > 0)
|
||||
data_to_sign = self._hash_ctx.finalize()
|
||||
buflen = self._backend._ffi.new("size_t *")
|
||||
res = self._backend._lib.EVP_PKEY_sign(
|
||||
|
@ -260,7 +258,7 @@ class _RSASignatureContext(object):
|
|||
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])
|
||||
res = self._backend._lib.EVP_PKEY_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):
|
||||
reason = ("Salt length too long for key size. Try using "
|
||||
"MAX_LENGTH instead.")
|
||||
elif (errors[0].reason ==
|
||||
self._backend._lib.RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY):
|
||||
else:
|
||||
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."
|
||||
assert reason is not None
|
||||
raise ValueError(reason)
|
||||
|
@ -333,24 +332,24 @@ class _RSASignatureContext(object):
|
|||
self._private_key._rsa_cdata,
|
||||
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]
|
||||
|
||||
|
||||
@utils.register_interface(interfaces.AsymmetricVerificationContext)
|
||||
@utils.register_interface(AsymmetricVerificationContext)
|
||||
class _RSAVerificationContext(object):
|
||||
def __init__(self, backend, public_key, signature, padding, algorithm):
|
||||
self._backend = backend
|
||||
self._public_key = public_key
|
||||
self._signature = signature
|
||||
|
||||
if not isinstance(padding, interfaces.AsymmetricPadding):
|
||||
raise TypeError(
|
||||
"Expected provider of interfaces.AsymmetricPadding.")
|
||||
if not isinstance(padding, AsymmetricPadding):
|
||||
raise TypeError("Expected provider of AsymmetricPadding.")
|
||||
|
||||
self._pkey_size = self._backend._lib.EVP_PKEY_size(
|
||||
self._public_key._evp_pkey
|
||||
)
|
||||
self._backend.openssl_assert(self._pkey_size > 0)
|
||||
|
||||
if isinstance(padding, PKCS1v15):
|
||||
if self._backend._lib.Cryptography_HAS_PKEY_CTX:
|
||||
|
@ -367,7 +366,6 @@ class _RSAVerificationContext(object):
|
|||
|
||||
# Size of key in bytes - 2 is the maximum
|
||||
# PSS signature length (salt length is checked later)
|
||||
assert self._pkey_size > 0
|
||||
if self._pkey_size - algorithm.digest_size - 2 < 0:
|
||||
raise ValueError(
|
||||
"Digest too large for key size. Check that you have the "
|
||||
|
@ -402,7 +400,7 @@ class _RSAVerificationContext(object):
|
|||
def verify(self):
|
||||
evp_md = self._backend._lib.EVP_get_digestbyname(
|
||||
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)
|
||||
|
||||
|
@ -410,18 +408,18 @@ class _RSAVerificationContext(object):
|
|||
pkey_ctx = self._backend._lib.EVP_PKEY_CTX_new(
|
||||
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,
|
||||
self._backend._lib.EVP_PKEY_CTX_free)
|
||||
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(
|
||||
pkey_ctx, evp_md)
|
||||
assert res > 0
|
||||
self._backend.openssl_assert(res > 0)
|
||||
|
||||
res = self._backend._lib.EVP_PKEY_CTX_set_rsa_padding(
|
||||
pkey_ctx, self._padding_enum)
|
||||
assert res > 0
|
||||
self._backend.openssl_assert(res > 0)
|
||||
if isinstance(self._padding, PSS):
|
||||
res = self._backend._lib.EVP_PKEY_CTX_set_rsa_pss_saltlen(
|
||||
pkey_ctx,
|
||||
|
@ -431,16 +429,18 @@ class _RSAVerificationContext(object):
|
|||
self._hash_ctx.algorithm.digest_size
|
||||
)
|
||||
)
|
||||
assert res > 0
|
||||
self._backend.openssl_assert(res > 0)
|
||||
if self._backend._lib.Cryptography_HAS_MGF1_MD:
|
||||
# MGF1 MD is configurable in OpenSSL 1.0.1+
|
||||
mgf1_md = self._backend._lib.EVP_get_digestbyname(
|
||||
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(
|
||||
pkey_ctx, mgf1_md
|
||||
)
|
||||
assert res > 0
|
||||
self._backend.openssl_assert(res > 0)
|
||||
|
||||
data_to_verify = self._hash_ctx.finalize()
|
||||
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
|
||||
# error. This is not a signature failure but we need to fail if it
|
||||
# occurs.
|
||||
assert res >= 0
|
||||
self._backend.openssl_assert(res >= 0)
|
||||
if res == 0:
|
||||
errors = self._backend._consume_errors()
|
||||
assert errors
|
||||
|
@ -473,7 +473,7 @@ class _RSAVerificationContext(object):
|
|||
# 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
|
||||
# occurs.
|
||||
assert res >= 0
|
||||
self._backend.openssl_assert(res >= 0)
|
||||
if res == 0:
|
||||
errors = self._backend._consume_errors()
|
||||
assert errors
|
||||
|
@ -511,26 +511,16 @@ class _RSAVerificationContext(object):
|
|||
raise InvalidSignature
|
||||
|
||||
|
||||
@utils.register_interface(RSAPrivateKeyWithNumbers)
|
||||
@utils.register_interface(RSAPrivateKeyWithSerialization)
|
||||
class _RSAPrivateKey(object):
|
||||
def __init__(self, backend, rsa_cdata):
|
||||
def __init__(self, backend, rsa_cdata, evp_pkey):
|
||||
self._backend = backend
|
||||
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._key_size = self._backend._lib.BN_num_bits(self._rsa_cdata.n)
|
||||
|
||||
@property
|
||||
def key_size(self):
|
||||
return self._key_size
|
||||
key_size = utils.read_only_property("_key_size")
|
||||
|
||||
def signer(self, padding, algorithm):
|
||||
return _RSASignatureContext(self._backend, self, padding, algorithm)
|
||||
|
@ -544,13 +534,14 @@ class _RSAPrivateKey(object):
|
|||
|
||||
def public_key(self):
|
||||
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.e = self._backend._lib.BN_dup(self._rsa_cdata.e)
|
||||
ctx.n = self._backend._lib.BN_dup(self._rsa_cdata.n)
|
||||
res = self._backend._lib.RSA_blinding_on(ctx, self._backend._ffi.NULL)
|
||||
assert res == 1
|
||||
return _RSAPublicKey(self._backend, ctx)
|
||||
self._backend.openssl_assert(res == 1)
|
||||
evp_pkey = self._backend._rsa_cdata_to_evp_pkey(ctx)
|
||||
return _RSAPublicKey(self._backend, ctx, evp_pkey)
|
||||
|
||||
def private_numbers(self):
|
||||
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):
|
||||
def __init__(self, backend, rsa_cdata):
|
||||
def __init__(self, backend, rsa_cdata, evp_pkey):
|
||||
self._backend = backend
|
||||
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._key_size = self._backend._lib.BN_num_bits(self._rsa_cdata.n)
|
||||
|
||||
@property
|
||||
def key_size(self):
|
||||
return self._key_size
|
||||
key_size = utils.read_only_property("_key_size")
|
||||
|
||||
def verifier(self, signature, padding, algorithm):
|
||||
if not isinstance(signature, bytes):
|
||||
raise TypeError("signature must be bytes.")
|
||||
|
||||
return _RSAVerificationContext(
|
||||
self._backend, self, signature, padding, algorithm
|
||||
)
|
||||
|
@ -601,3 +594,11 @@ class _RSAPublicKey(object):
|
|||
e=self._backend._bn_to_int(self._rsa_cdata.e),
|
||||
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");
|
||||
# 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.
|
||||
# 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
|
||||
|
|
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");
|
||||
# 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.
|
||||
# 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
|
||||
|
|
|
@ -1,54 +1,15 @@
|
|||
# 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.
|
||||
# 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
|
||||
|
||||
from cryptography.hazmat.bindings.utils import build_ffi
|
||||
from cryptography.hazmat.bindings._commoncrypto import ffi, lib
|
||||
|
||||
|
||||
class Binding(object):
|
||||
"""
|
||||
CommonCrypto API wrapper.
|
||||
"""
|
||||
_module_prefix = "cryptography.hazmat.bindings.commoncrypto."
|
||||
_modules = [
|
||||
"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"
|
||||
]
|
||||
)
|
||||
lib = lib
|
||||
ffi = ffi
|
||||
|
|
|
@ -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");
|
||||
# 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.
|
||||
# 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
|
||||
|
|
|
@ -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");
|
||||
# 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.
|
||||
# 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 collections
|
||||
import os
|
||||
import sys
|
||||
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 = """
|
||||
#ifdef __APPLE__
|
||||
#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
|
||||
"""
|
||||
_OpenSSLError = collections.namedtuple("_OpenSSLError",
|
||||
["code", "lib", "func", "reason"])
|
||||
|
||||
_OSX_POST_INCLUDE = """
|
||||
#ifdef __APPLE__
|
||||
#undef DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
|
||||
#define DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER \
|
||||
__ORIG_DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
|
||||
#endif
|
||||
"""
|
||||
|
||||
def _consume_errors(lib):
|
||||
errors = []
|
||||
while True:
|
||||
code = lib.ERR_get_error()
|
||||
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):
|
||||
"""
|
||||
OpenSSL API wrapper.
|
||||
"""
|
||||
_module_prefix = "cryptography.hazmat.bindings.openssl."
|
||||
_modules = [
|
||||
"aes",
|
||||
"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"
|
||||
]
|
||||
|
||||
lib = None
|
||||
ffi = ffi
|
||||
_lib_loaded = False
|
||||
_locks = None
|
||||
_lock_cb_handle = None
|
||||
_init_lock = threading.Lock()
|
||||
_lock_init_lock = threading.Lock()
|
||||
|
||||
ffi = None
|
||||
lib = None
|
||||
_osrandom_engine_id = ffi.new("const char[]", b"osrandom")
|
||||
_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):
|
||||
self._ensure_ffi_initialized()
|
||||
|
||||
@classmethod
|
||||
def _ensure_ffi_initialized(cls):
|
||||
if cls.ffi is not None and cls.lib is not None:
|
||||
return
|
||||
def _register_osrandom_engine(cls):
|
||||
_openssl_assert(cls.lib, cls.lib.ERR_peek_error() == 0)
|
||||
|
||||
# OpenSSL goes by a different library name on different operating
|
||||
# systems.
|
||||
if sys.platform != "win32":
|
||||
# In some circumstances, the order in which these libs are
|
||||
# specified on the linker command-line is significant;
|
||||
# libssl must come before libcrypto
|
||||
# (http://marc.info/?l=openssl-users&m=135361825921871)
|
||||
libraries = ["ssl", "crypto"]
|
||||
else: # pragma: no cover
|
||||
link_type = os.environ.get("PYCA_WINDOWS_LINK_TYPE", "static")
|
||||
libraries = _get_windows_libraries(link_type)
|
||||
|
||||
cls.ffi, cls.lib = build_ffi(
|
||||
module_prefix=cls._module_prefix,
|
||||
modules=cls._modules,
|
||||
pre_include=_OSX_PRE_INCLUDE,
|
||||
post_include=_OSX_POST_INCLUDE,
|
||||
libraries=libraries,
|
||||
engine = cls.lib.ENGINE_new()
|
||||
_openssl_assert(cls.lib, engine != cls.ffi.NULL)
|
||||
try:
|
||||
result = cls.lib.ENGINE_set_id(engine, cls._osrandom_engine_id)
|
||||
_openssl_assert(cls.lib, result == 1)
|
||||
result = cls.lib.ENGINE_set_name(engine, cls._osrandom_engine_name)
|
||||
_openssl_assert(cls.lib, result == 1)
|
||||
result = cls.lib.ENGINE_set_RAND(engine, cls._osrandom_method)
|
||||
_openssl_assert(cls.lib, result == 1)
|
||||
result = cls.lib.ENGINE_add(engine)
|
||||
if result != 1:
|
||||
errors = _consume_errors(cls.lib)
|
||||
_openssl_assert(
|
||||
cls.lib,
|
||||
errors[0].reason == cls.lib.ENGINE_R_CONFLICTING_ENGINE_ID
|
||||
)
|
||||
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
|
||||
def init_static_locks(cls):
|
||||
|
@ -156,13 +174,9 @@ class Binding(object):
|
|||
)
|
||||
|
||||
|
||||
def _get_windows_libraries(link_type):
|
||||
if link_type == "dynamic":
|
||||
return ["libeay32", "ssleay32", "advapi32"]
|
||||
elif link_type == "static" or link_type == "":
|
||||
return ["libeay32mt", "ssleay32mt", "advapi32",
|
||||
"crypt32", "gdi32", "user32", "ws2_32"]
|
||||
else:
|
||||
raise ValueError(
|
||||
"PYCA_WINDOWS_LINK_TYPE must be 'static' or 'dynamic'"
|
||||
)
|
||||
# OpenSSL is not thread safe until the locks are initialized. We call this
|
||||
# method in module scope so that it executes with the import lock. On
|
||||
# Pythons < 3.4 this import lock is a global lock, which can prevent a race
|
||||
# condition registering the OpenSSL locks. On Python 3.4+ the import lock
|
||||
# is per module so this approach will not work.
|
||||
Binding.init_static_locks()
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue