Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
c2fc7c4f
Commit
c2fc7c4f
authored
Sep 05, 2016
by
Christian Heimes
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Issue #26470: Port ssl and hashlib module to OpenSSL 1.1.0.
parent
34458277
Changes
6
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
342 additions
and
135 deletions
+342
-135
Doc/library/ssl.rst
Doc/library/ssl.rst
+49
-2
Lib/ssl.py
Lib/ssl.py
+10
-6
Lib/test/test_ssl.py
Lib/test/test_ssl.py
+40
-26
Misc/NEWS
Misc/NEWS
+2
-0
Modules/_hashopenssl.c
Modules/_hashopenssl.c
+110
-60
Modules/_ssl.c
Modules/_ssl.c
+131
-41
No files found.
Doc/library/ssl.rst
View file @
c2fc7c4f
...
...
@@ -322,6 +322,16 @@ purposes.
Random generation
^^^^^^^^^^^^^^^^^
.. deprecated::
2.7.13 OpenSSL has deprecated :func:`ssl.RAND_pseudo_bytes`, use
:func:`ssl.RAND_bytes` instead.
.. deprecated::
2.7.13 OpenSSL has deprecated :func:`ssl.RAND_pseudo_bytes`, use
:func:`ssl.RAND_bytes` instead.
.. function:: RAND_status()
Return ``True`` if the SSL pseudo-random number generator has been seeded
...
...
@@ -340,7 +350,7 @@ Random generation
See http://egd.sourceforge.net/ or http://prngd.sourceforge.net/ for sources
of entropy-gathering daemons.
Availability: not available with LibreSSL
.
Availability: not available with LibreSSL
and OpenSSL > 1.1.0
.. function:: RAND_add(bytes, entropy)
...
...
@@ -444,6 +454,9 @@ Certificate handling
* :attr:`openssl_capath_env` - OpenSSL's environment key that points to a capath,
* :attr:`openssl_capath` - hard coded path to a capath directory
Availability: LibreSSL ignores the environment vars
:attr:`openssl_cafile_env` and :attr:`openssl_capath_env`
.. versionadded:: 2.7.9
.. function:: enum_certificates(store_name)
...
...
@@ -561,11 +574,19 @@ Constants
.. versionadded:: 2.7.10
.. data:: PROTOCOL_
SSLv23
.. data:: PROTOCOL_
TLS
Selects the highest protocol version that both the client and server support.
Despite the name, this option can select "TLS" protocols as well as "SSL".
.. versionadded:: 2.7.13
.. data:: PROTOCOL_SSLv23
Alias for ``PROTOCOL_TLS``.
.. deprecated:: 2.7.13 Use ``PROTOCOL_TLS`` instead.
.. data:: PROTOCOL_SSLv2
Selects SSL version 2 as the channel encryption protocol.
...
...
@@ -577,6 +598,8 @@ Constants
SSL version 2 is insecure. Its use is highly discouraged.
.. deprecated:: 2.7.13 OpenSSL has removed support for SSLv2.
.. data:: PROTOCOL_SSLv3
Selects SSL version 3 as the channel encryption protocol.
...
...
@@ -588,10 +611,20 @@ Constants
SSL version 3 is insecure. Its use is highly discouraged.
.. deprecated:: 2.7.13
OpenSSL has deprecated all version specific protocols. Use the default
protocol with flags like ``OP_NO_SSLv3`` instead.
.. data:: PROTOCOL_TLSv1
Selects TLS version 1.0 as the channel encryption protocol.
.. deprecated:: 2.7.13
OpenSSL has deprecated all version specific protocols. Use the default
protocol with flags like ``OP_NO_SSLv3`` instead.
.. data:: PROTOCOL_TLSv1_1
Selects TLS version 1.1 as the channel encryption protocol.
...
...
@@ -599,6 +632,11 @@ Constants
.. versionadded:: 2.7.9
.. deprecated:: 2.7.13
OpenSSL has deprecated all version specific protocols. Use the default
protocol with flags like ``OP_NO_SSLv3`` instead.
.. data:: PROTOCOL_TLSv1_2
Selects TLS version 1.2 as the channel encryption protocol. This is the
...
...
@@ -607,6 +645,12 @@ Constants
.. versionadded:: 2.7.9
.. deprecated:: 2.7.13
OpenSSL has deprecated all version specific protocols. Use the default
protocol with flags like ``OP_NO_SSLv3`` instead.
.. data:: OP_ALL
Enables workarounds for various bugs present in other SSL implementations.
...
...
@@ -1112,6 +1156,9 @@ to speed up repeated connections from the same clients.
This method will raise :exc:`NotImplementedError` if :data:`HAS_ALPN` is
False.
OpenSSL 1.1.0+ will abort the handshake and raise :exc:`SSLError` when
both sides support ALPN but cannot agree on a protocol.
.. versionadded:: 2.7.10
.. method:: SSLContext.set_npn_protocols(protocols)
...
...
Lib/ssl.py
View file @
c2fc7c4f
...
...
@@ -51,6 +51,7 @@ The following constants identify various SSL protocol variants:
PROTOCOL_SSLv2
PROTOCOL_SSLv3
PROTOCOL_SSLv23
PROTOCOL_TLS
PROTOCOL_TLSv1
PROTOCOL_TLSv1_1
PROTOCOL_TLSv1_2
...
...
@@ -126,7 +127,10 @@ from _ssl import HAS_SNI, HAS_ECDH, HAS_NPN, HAS_ALPN
from
_ssl
import
_OPENSSL_API_VERSION
_PROTOCOL_NAMES
=
{
value
:
name
for
name
,
value
in
globals
().
items
()
if
name
.
startswith
(
'PROTOCOL_'
)}
_PROTOCOL_NAMES
=
{
value
:
name
for
name
,
value
in
globals
().
items
()
if
name
.
startswith
(
'PROTOCOL_'
)
and
name
!=
'PROTOCOL_SSLv23'
}
PROTOCOL_SSLv23
=
PROTOCOL_TLS
try
:
_SSLv2_IF_EXISTS
=
PROTOCOL_SSLv2
...
...
@@ -408,7 +412,7 @@ def create_default_context(purpose=Purpose.SERVER_AUTH, cafile=None,
if not isinstance(purpose, _ASN1Object):
raise TypeError(purpose)
context = SSLContext(PROTOCOL_
SSLv23
)
context = SSLContext(PROTOCOL_
TLS
)
# SSLv2 considered harmful.
context.options |= OP_NO_SSLv2
...
...
@@ -445,7 +449,7 @@ def create_default_context(purpose=Purpose.SERVER_AUTH, cafile=None,
context
.
load_default_certs
(
purpose
)
return
context
def
_create_unverified_context
(
protocol
=
PROTOCOL_
SSLv23
,
cert_reqs
=
None
,
def
_create_unverified_context
(
protocol
=
PROTOCOL_
TLS
,
cert_reqs
=
None
,
check_hostname
=
False
,
purpose
=
Purpose
.
SERVER_AUTH
,
certfile
=
None
,
keyfile
=
None
,
cafile
=
None
,
capath
=
None
,
cadata
=
None
):
...
...
@@ -518,7 +522,7 @@ class SSLSocket(socket):
def
__init__
(
self
,
sock
=
None
,
keyfile
=
None
,
certfile
=
None
,
server_side
=
False
,
cert_reqs
=
CERT_NONE
,
ssl_version
=
PROTOCOL_
SSLv23
,
ca_certs
=
None
,
ssl_version
=
PROTOCOL_
TLS
,
ca_certs
=
None
,
do_handshake_on_connect
=
True
,
family
=
AF_INET
,
type
=
SOCK_STREAM
,
proto
=
0
,
fileno
=
None
,
suppress_ragged_eofs
=
True
,
npn_protocols
=
None
,
ciphers
=
None
,
...
...
@@ -920,7 +924,7 @@ class SSLSocket(socket):
def
wrap_socket
(
sock
,
keyfile
=
None
,
certfile
=
None
,
server_side
=
False
,
cert_reqs
=
CERT_NONE
,
ssl_version
=
PROTOCOL_
SSLv23
,
ca_certs
=
None
,
ssl_version
=
PROTOCOL_
TLS
,
ca_certs
=
None
,
do_handshake_on_connect
=
True
,
suppress_ragged_eofs
=
True
,
ciphers
=
None
):
...
...
@@ -989,7 +993,7 @@ def PEM_cert_to_DER_cert(pem_cert_string):
d
=
pem_cert_string
.
strip
()[
len
(
PEM_HEADER
):
-
len
(
PEM_FOOTER
)]
return
base64
.
decodestring
(
d
.
encode
(
'ASCII'
,
'strict'
))
def
get_server_certificate
(
addr
,
ssl_version
=
PROTOCOL_
SSLv23
,
ca_certs
=
None
):
def
get_server_certificate
(
addr
,
ssl_version
=
PROTOCOL_
TLS
,
ca_certs
=
None
):
"""Retrieve the certificate from the server at the specified address,
and return it as a PEM-encoded string.
If 'ca_certs' is specified, validate the server cert against it.
...
...
Lib/test/test_ssl.py
View file @
c2fc7c4f
...
...
@@ -26,6 +26,9 @@ ssl = support.import_module("ssl")
PROTOCOLS
=
sorted
(
ssl
.
_PROTOCOL_NAMES
)
HOST
=
support
.
HOST
IS_LIBRESSL
=
ssl
.
OPENSSL_VERSION
.
startswith
(
'LibreSSL'
)
IS_OPENSSL_1_1
=
not
IS_LIBRESSL
and
ssl
.
OPENSSL_VERSION_INFO
>=
(
1
,
1
,
0
)
def
data_file
(
*
name
):
return
os
.
path
.
join
(
os
.
path
.
dirname
(
__file__
),
*
name
)
...
...
@@ -164,7 +167,6 @@ class BasicSocketTests(unittest.TestCase):
self
.
assertIn
(
ssl
.
HAS_SNI
,
{
True
,
False
})
self
.
assertIn
(
ssl
.
HAS_ECDH
,
{
True
,
False
})
def
test_random
(
self
):
v
=
ssl
.
RAND_status
()
if
support
.
verbose
:
...
...
@@ -281,9 +283,9 @@ class BasicSocketTests(unittest.TestCase):
self
.
assertGreaterEqual
(
status
,
0
)
self
.
assertLessEqual
(
status
,
15
)
# Version string as returned by {Open,Libre}SSL, the format might change
if
"LibreSSL"
in
s
:
self
.
assertTrue
(
s
.
startswith
(
"LibreSSL {:d}
.{:d}"
.
format
(
major
,
min
or
)),
(
s
,
t
))
if
IS_LIBRESSL
:
self
.
assertTrue
(
s
.
startswith
(
"LibreSSL {:d}
"
.
format
(
maj
or
)),
(
s
,
t
,
hex
(
n
)
))
else
:
self
.
assertTrue
(
s
.
startswith
(
"OpenSSL {:d}.{:d}.{:d}"
.
format
(
major
,
minor
,
fix
)),
(
s
,
t
))
...
...
@@ -742,15 +744,15 @@ class ContextTests(unittest.TestCase):
def
test_options
(
self
):
ctx
=
ssl
.
SSLContext
(
ssl
.
PROTOCOL_TLSv1
)
# OP_ALL | OP_NO_SSLv2 | OP_NO_SSLv3 is the default value
self
.
assertEqual
(
ssl
.
OP_ALL
|
ssl
.
OP_NO_SSLv2
|
ssl
.
OP_NO_SSLv3
,
ctx
.
options
)
default
=
(
ssl
.
OP_ALL
|
ssl
.
OP_NO_SSLv2
|
ssl
.
OP_NO_SSLv3
)
if
not
IS_LIBRESSL
and
ssl
.
OPENSSL_VERSION_INFO
>=
(
1
,
1
,
0
):
default
|=
ssl
.
OP_NO_COMPRESSION
self
.
assertEqual
(
default
,
ctx
.
options
)
ctx
.
options
|=
ssl
.
OP_NO_TLSv1
self
.
assertEqual
(
ssl
.
OP_ALL
|
ssl
.
OP_NO_SSLv2
|
ssl
.
OP_NO_SSLv3
|
ssl
.
OP_NO_TLSv1
,
ctx
.
options
)
self
.
assertEqual
(
default
|
ssl
.
OP_NO_TLSv1
,
ctx
.
options
)
if
can_clear_options
():
ctx
.
options
=
(
ctx
.
options
&
~
ssl
.
OP_NO_SSLv2
)
|
ssl
.
OP_NO_TLSv1
self
.
assertEqual
(
ssl
.
OP_ALL
|
ssl
.
OP_NO_TLSv1
|
ssl
.
OP_NO_SSLv3
,
ctx
.
options
)
ctx
.
options
=
(
ctx
.
options
&
~
ssl
.
OP_NO_TLSv1
)
self
.
assertEqual
(
default
,
ctx
.
options
)
ctx
.
options
=
0
self
.
assertEqual
(
0
,
ctx
.
options
)
else
:
...
...
@@ -1088,6 +1090,7 @@ class ContextTests(unittest.TestCase):
self
.
assertRaises
(
TypeError
,
ctx
.
load_default_certs
,
'SERVER_AUTH'
)
@
unittest
.
skipIf
(
sys
.
platform
==
"win32"
,
"not-Windows specific"
)
@
unittest
.
skipIf
(
IS_LIBRESSL
,
"LibreSSL doesn't support env vars"
)
def
test_load_default_certs_env
(
self
):
ctx
=
ssl
.
SSLContext
(
ssl
.
PROTOCOL_TLSv1
)
with
support
.
EnvironmentVarGuard
()
as
env
:
...
...
@@ -1534,7 +1537,6 @@ class NetworkedTests(unittest.TestCase):
sys
.
stdout
.
write
(
"%s
\
n
"
%
x
)
else
:
self
.
fail
(
"Got server certificate %s for %s:%s!"
%
(
pem
,
host
,
port
))
pem
=
ssl
.
get_server_certificate
((
host
,
port
),
ca_certs
=
cert
)
if
not
pem
:
...
...
@@ -2783,7 +2785,7 @@ else:
with
closing
(
context
.
wrap_socket
(
socket
.
socket
()))
as
s
:
self
.
assertIs
(
s
.
version
(),
None
)
s
.
connect
((
HOST
,
server
.
port
))
self
.
assertEqual
(
s
.
version
(),
"TLSv1"
)
self
.
assertEqual
(
s
.
version
(),
'TLSv1'
)
self
.
assertIs
(
s
.
version
(),
None
)
@
unittest
.
skipUnless
(
ssl
.
HAS_ECDH
,
"test requires ECDH-enabled OpenSSL"
)
...
...
@@ -2925,24 +2927,36 @@ else:
([
'http/3.0'
,
'http/4.0'
],
None
)
]
for
client_protocols
,
expected
in
protocol_tests
:
server_context
=
ssl
.
SSLContext
(
ssl
.
PROTOCOL_TLSv1
)
server_context
=
ssl
.
SSLContext
(
ssl
.
PROTOCOL_TLSv1
_2
)
server_context
.
load_cert_chain
(
CERTFILE
)
server_context
.
set_alpn_protocols
(
server_protocols
)
client_context
=
ssl
.
SSLContext
(
ssl
.
PROTOCOL_TLSv1
)
client_context
=
ssl
.
SSLContext
(
ssl
.
PROTOCOL_TLSv1
_2
)
client_context
.
load_cert_chain
(
CERTFILE
)
client_context
.
set_alpn_protocols
(
client_protocols
)
stats
=
server_params_test
(
client_context
,
server_context
,
chatty
=
True
,
connectionchatty
=
True
)
msg
=
"failed trying %s (s) and %s (c).
\
n
"
\
"was expecting %s, but got %%s from the %%s"
\
%
(
str
(
server_protocols
),
str
(
client_protocols
),
str
(
expected
))
client_result
=
stats
[
'client_alpn_protocol'
]
self
.
assertEqual
(
client_result
,
expected
,
msg
%
(
client_result
,
"client"
))
server_result
=
stats
[
'server_alpn_protocols'
][
-
1
]
\
if
len
(
stats
[
'server_alpn_protocols'
])
else
'nothing'
self
.
assertEqual
(
server_result
,
expected
,
msg
%
(
server_result
,
"server"
))
try
:
stats
=
server_params_test
(
client_context
,
server_context
,
chatty
=
True
,
connectionchatty
=
True
)
except
ssl
.
SSLError
as
e
:
stats
=
e
if
expected
is
None
and
IS_OPENSSL_1_1
:
# OpenSSL 1.1.0 raises handshake error
self
.
assertIsInstance
(
stats
,
ssl
.
SSLError
)
else
:
msg
=
"failed trying %s (s) and %s (c).
\
n
"
\
"was expecting %s, but got %%s from the %%s"
\
%
(
str
(
server_protocols
),
str
(
client_protocols
),
str
(
expected
))
client_result
=
stats
[
'client_alpn_protocol'
]
self
.
assertEqual
(
client_result
,
expected
,
msg
%
(
client_result
,
"client"
))
server_result
=
stats
[
'server_alpn_protocols'
][
-
1
]
\
if
len
(
stats
[
'server_alpn_protocols'
])
else
'nothing'
self
.
assertEqual
(
server_result
,
expected
,
msg
%
(
server_result
,
"server"
))
def
test_selected_npn_protocol
(
self
):
# selected_npn_protocol() is None unless NPN is used
...
...
Misc/NEWS
View file @
c2fc7c4f
...
...
@@ -36,6 +36,8 @@ Core and Builtins
Library
-------
-
Issue
#
26470
:
Port
ssl
and
hashlib
module
to
OpenSSL
1.1.0
.
-
Issue
#
27944
:
Fix
some
memory
-
corruption
bugs
in
the
log
reading
code
of
the
_hotshot
module
.
...
...
Modules/_hashopenssl.c
View file @
c2fc7c4f
...
...
@@ -37,8 +37,10 @@
/* EVP is the preferred interface to hashing in OpenSSL */
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <openssl/err.h>
/* We use the object interface to discover what hashes OpenSSL supports. */
#include <openssl/objects.h>
#include "openssl/err.h"
#define MUNCH_SIZE INT_MAX
...
...
@@ -50,15 +52,26 @@
#define HASH_OBJ_CONSTRUCTOR 0
#endif
/* Minimum OpenSSL version needed to support sha224 and higher. */
#if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x00908000)
#define _OPENSSL_SUPPORTS_SHA2
#endif
#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER)
/* OpenSSL < 1.1.0 */
#define EVP_MD_CTX_new EVP_MD_CTX_create
#define EVP_MD_CTX_free EVP_MD_CTX_destroy
#define HAS_FAST_PKCS5_PBKDF2_HMAC 0
#include <openssl/hmac.h>
#else
/* OpenSSL >= 1.1.0 */
#define HAS_FAST_PKCS5_PBKDF2_HMAC 1
#endif
typedef
struct
{
PyObject_HEAD
PyObject
*
name
;
/* name of this hash algorithm */
EVP_MD_CTX
ctx
;
/* OpenSSL message digest context */
EVP_MD_CTX
*
ctx
;
/* OpenSSL message digest context */
#ifdef WITH_THREAD
PyThread_type_lock
lock
;
/* OpenSSL context lock */
#endif
...
...
@@ -70,7 +83,6 @@ static PyTypeObject EVPtype;
#define DEFINE_CONSTS_FOR_NEW(Name) \
static PyObject *CONST_ ## Name ## _name_obj = NULL; \
static EVP_MD_CTX CONST_new_ ## Name ## _ctx; \
static EVP_MD_CTX *CONST_new_ ## Name ## _ctx_p = NULL;
DEFINE_CONSTS_FOR_NEW
(
md5
)
...
...
@@ -83,19 +95,56 @@ DEFINE_CONSTS_FOR_NEW(sha512)
#endif
/* LCOV_EXCL_START */
static
PyObject
*
_setException
(
PyObject
*
exc
)
{
unsigned
long
errcode
;
const
char
*
lib
,
*
func
,
*
reason
;
errcode
=
ERR_peek_last_error
();
if
(
!
errcode
)
{
PyErr_SetString
(
exc
,
"unknown reasons"
);
return
NULL
;
}
ERR_clear_error
();
lib
=
ERR_lib_error_string
(
errcode
);
func
=
ERR_func_error_string
(
errcode
);
reason
=
ERR_reason_error_string
(
errcode
);
if
(
lib
&&
func
)
{
PyErr_Format
(
exc
,
"[%s: %s] %s"
,
lib
,
func
,
reason
);
}
else
if
(
lib
)
{
PyErr_Format
(
exc
,
"[%s] %s"
,
lib
,
reason
);
}
else
{
PyErr_SetString
(
exc
,
reason
);
}
return
NULL
;
}
/* LCOV_EXCL_STOP */
static
EVPobject
*
newEVPobject
(
PyObject
*
name
)
{
EVPobject
*
retval
=
(
EVPobject
*
)
PyObject_New
(
EVPobject
,
&
EVPtype
);
if
(
retval
==
NULL
)
return
NULL
;
retval
->
ctx
=
EVP_MD_CTX_new
();
if
(
retval
->
ctx
==
NULL
)
{
PyErr_NoMemory
();
return
NULL
;
}
/* save the name for .name to return */
if
(
retval
!=
NULL
)
{
Py_INCREF
(
name
);
retval
->
name
=
name
;
Py_INCREF
(
name
);
retval
->
name
=
name
;
#ifdef WITH_THREAD
retval
->
lock
=
NULL
;
retval
->
lock
=
NULL
;
#endif
}
return
retval
;
}
...
...
@@ -111,7 +160,7 @@ EVP_hash(EVPobject *self, const void *vp, Py_ssize_t len)
process
=
MUNCH_SIZE
;
else
process
=
Py_SAFE_DOWNCAST
(
len
,
Py_ssize_t
,
unsigned
int
);
EVP_DigestUpdate
(
&
self
->
ctx
,
(
const
void
*
)
cp
,
process
);
EVP_DigestUpdate
(
self
->
ctx
,
(
const
void
*
)
cp
,
process
);
len
-=
process
;
cp
+=
process
;
}
...
...
@@ -126,16 +175,20 @@ EVP_dealloc(EVPobject *self)
if
(
self
->
lock
!=
NULL
)
PyThread_free_lock
(
self
->
lock
);
#endif
EVP_MD_CTX_
cleanup
(
&
self
->
ctx
);
EVP_MD_CTX_
free
(
self
->
ctx
);
Py_XDECREF
(
self
->
name
);
PyObject_Del
(
self
);
}
static
void
locked_EVP_MD_CTX_copy
(
EVP_MD_CTX
*
new_ctx_p
,
EVPobject
*
self
)
static
int
locked_EVP_MD_CTX_copy
(
EVP_MD_CTX
*
new_ctx_p
,
EVPobject
*
self
)
{
int
result
;
ENTER_HASHLIB
(
self
);
EVP_MD_CTX_copy
(
new_ctx_p
,
&
self
->
ctx
);
/* XXX no error reporting */
result
=
EVP_MD_CTX_copy
(
new_ctx_p
,
self
->
ctx
);
LEAVE_HASHLIB
(
self
);
return
result
;
}
/* External methods for a hash object */
...
...
@@ -151,7 +204,9 @@ EVP_copy(EVPobject *self, PyObject *unused)
if
(
(
newobj
=
newEVPobject
(
self
->
name
))
==
NULL
)
return
NULL
;
locked_EVP_MD_CTX_copy
(
&
newobj
->
ctx
,
self
);
if
(
!
locked_EVP_MD_CTX_copy
(
newobj
->
ctx
,
self
))
{
return
_setException
(
PyExc_ValueError
);
}
return
(
PyObject
*
)
newobj
;
}
...
...
@@ -162,16 +217,24 @@ static PyObject *
EVP_digest
(
EVPobject
*
self
,
PyObject
*
unused
)
{
unsigned
char
digest
[
EVP_MAX_MD_SIZE
];
EVP_MD_CTX
temp_ctx
;
EVP_MD_CTX
*
temp_ctx
;
PyObject
*
retval
;
unsigned
int
digest_size
;
locked_EVP_MD_CTX_copy
(
&
temp_ctx
,
self
);
digest_size
=
EVP_MD_CTX_size
(
&
temp_ctx
);
EVP_DigestFinal
(
&
temp_ctx
,
digest
,
NULL
);
temp_ctx
=
EVP_MD_CTX_new
();
if
(
temp_ctx
==
NULL
)
{
PyErr_NoMemory
();
return
NULL
;
}
if
(
!
locked_EVP_MD_CTX_copy
(
temp_ctx
,
self
))
{
return
_setException
(
PyExc_ValueError
);
}
digest_size
=
EVP_MD_CTX_size
(
temp_ctx
);
EVP_DigestFinal
(
temp_ctx
,
digest
,
NULL
);
retval
=
PyString_FromStringAndSize
((
const
char
*
)
digest
,
digest_size
);
EVP_MD_CTX_
cleanup
(
&
temp_ctx
);
EVP_MD_CTX_
free
(
temp_ctx
);
return
retval
;
}
...
...
@@ -182,17 +245,25 @@ static PyObject *
EVP_hexdigest
(
EVPobject
*
self
,
PyObject
*
unused
)
{
unsigned
char
digest
[
EVP_MAX_MD_SIZE
];
EVP_MD_CTX
temp_ctx
;
EVP_MD_CTX
*
temp_ctx
;
PyObject
*
retval
;
char
*
hex_digest
;
unsigned
int
i
,
j
,
digest_size
;
temp_ctx
=
EVP_MD_CTX_new
();
if
(
temp_ctx
==
NULL
)
{
PyErr_NoMemory
();
return
NULL
;
}
/* Get the raw (binary) digest value */
locked_EVP_MD_CTX_copy
(
&
temp_ctx
,
self
);
digest_size
=
EVP_MD_CTX_size
(
&
temp_ctx
);
EVP_DigestFinal
(
&
temp_ctx
,
digest
,
NULL
);
if
(
!
locked_EVP_MD_CTX_copy
(
temp_ctx
,
self
))
{
return
_setException
(
PyExc_ValueError
);
}
digest_size
=
EVP_MD_CTX_size
(
temp_ctx
);
EVP_DigestFinal
(
temp_ctx
,
digest
,
NULL
);
EVP_MD_CTX_
cleanup
(
&
temp_ctx
);
EVP_MD_CTX_
free
(
temp_ctx
);
/* Create a new string */
/* NOTE: not thread safe! modifying an already created string object */
...
...
@@ -266,7 +337,7 @@ static PyObject *
EVP_get_block_size
(
EVPobject
*
self
,
void
*
closure
)
{
long
block_size
;
block_size
=
EVP_MD_CTX_block_size
(
&
self
->
ctx
);
block_size
=
EVP_MD_CTX_block_size
(
self
->
ctx
);
return
PyLong_FromLong
(
block_size
);
}
...
...
@@ -274,7 +345,7 @@ static PyObject *
EVP_get_digest_size
(
EVPobject
*
self
,
void
*
closure
)
{
long
size
;
size
=
EVP_MD_CTX_size
(
&
self
->
ctx
);
size
=
EVP_MD_CTX_size
(
self
->
ctx
);
return
PyLong_FromLong
(
size
);
}
...
...
@@ -338,7 +409,7 @@ EVP_tp_init(EVPobject *self, PyObject *args, PyObject *kwds)
PyBuffer_Release
(
&
view
);
return
-
1
;
}
EVP_DigestInit
(
&
self
->
ctx
,
digest
);
EVP_DigestInit
(
self
->
ctx
,
digest
);
self
->
name
=
name_obj
;
Py_INCREF
(
self
->
name
);
...
...
@@ -435,9 +506,9 @@ EVPnew(PyObject *name_obj,
return
NULL
;
if
(
initial_ctx
)
{
EVP_MD_CTX_copy
(
&
self
->
ctx
,
initial_ctx
);
EVP_MD_CTX_copy
(
self
->
ctx
,
initial_ctx
);
}
else
{
EVP_DigestInit
(
&
self
->
ctx
,
digest
);
EVP_DigestInit
(
self
->
ctx
,
digest
);
}
if
(
cp
&&
len
)
{
...
...
@@ -499,6 +570,7 @@ EVP_new(PyObject *self, PyObject *args, PyObject *kwdict)
#define PY_PBKDF2_HMAC 1
#if !HAS_FAST_PKCS5_PBKDF2_HMAC
/* Improved implementation of PKCS5_PBKDF2_HMAC()
*
* PKCS5_PBKDF2_HMAC_fast() hashes the password exactly one time instead of
...
...
@@ -580,37 +652,8 @@ PKCS5_PBKDF2_HMAC_fast(const char *pass, int passlen,
HMAC_CTX_cleanup
(
&
hctx_tpl
);
return
1
;
}
#endif
/* LCOV_EXCL_START */
static
PyObject
*
_setException
(
PyObject
*
exc
)
{
unsigned
long
errcode
;
const
char
*
lib
,
*
func
,
*
reason
;
errcode
=
ERR_peek_last_error
();
if
(
!
errcode
)
{
PyErr_SetString
(
exc
,
"unknown reasons"
);
return
NULL
;
}
ERR_clear_error
();
lib
=
ERR_lib_error_string
(
errcode
);
func
=
ERR_func_error_string
(
errcode
);
reason
=
ERR_reason_error_string
(
errcode
);
if
(
lib
&&
func
)
{
PyErr_Format
(
exc
,
"[%s: %s] %s"
,
lib
,
func
,
reason
);
}
else
if
(
lib
)
{
PyErr_Format
(
exc
,
"[%s] %s"
,
lib
,
reason
);
}
else
{
PyErr_SetString
(
exc
,
reason
);
}
return
NULL
;
}
/* LCOV_EXCL_STOP */
PyDoc_STRVAR
(
pbkdf2_hmac__doc__
,
"pbkdf2_hmac(hash_name, password, salt, iterations, dklen=None) -> key
\n
\
...
...
@@ -692,10 +735,17 @@ pbkdf2_hmac(PyObject *self, PyObject *args, PyObject *kwdict)
key
=
PyBytes_AS_STRING
(
key_obj
);
Py_BEGIN_ALLOW_THREADS
#if HAS_FAST_PKCS5_PBKDF2_HMAC
retval
=
PKCS5_PBKDF2_HMAC
((
char
*
)
password
.
buf
,
(
int
)
password
.
len
,
(
unsigned
char
*
)
salt
.
buf
,
(
int
)
salt
.
len
,
iterations
,
digest
,
dklen
,
(
unsigned
char
*
)
key
);
#else
retval
=
PKCS5_PBKDF2_HMAC_fast
((
char
*
)
password
.
buf
,
(
int
)
password
.
len
,
(
unsigned
char
*
)
salt
.
buf
,
(
int
)
salt
.
len
,
iterations
,
digest
,
dklen
,
(
unsigned
char
*
)
key
);
#endif
Py_END_ALLOW_THREADS
if
(
!
retval
)
{
...
...
@@ -807,7 +857,7 @@ generate_hash_name_list(void)
if (CONST_ ## NAME ## _name_obj == NULL) { \
CONST_ ## NAME ## _name_obj = PyString_FromString(#NAME); \
if (EVP_get_digestbyname(#NAME)) { \
CONST_new_ ## NAME ## _ctx_p =
&CONST_new_ ## NAME ## _ctx
; \
CONST_new_ ## NAME ## _ctx_p =
EVP_MD_CTX_new()
; \
EVP_DigestInit(CONST_new_ ## NAME ## _ctx_p, EVP_get_digestbyname(#NAME)); \
} \
} \
...
...
Modules/_ssl.c
View file @
c2fc7c4f
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment