aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Gaynor <alex.gaynor@gmail.com>2014-10-03 14:53:46 -0700
committerAlex Gaynor <alex.gaynor@gmail.com>2014-10-03 14:53:46 -0700
commit58c46c22e74e641d176537fb6cc4b593cad3e2b1 (patch)
tree2cccb38345d3a2b6f10bdaf7575c06a9fd83d714
parent65cc34d2b1f7a4a7d1e96e2f448e43c5be74ac7a (diff)
parentbb20dd5fb7d55f4ccea3dd5a3a32536722d3456b (diff)
downloadcryptography-58c46c22e74e641d176537fb6cc4b593cad3e2b1.tar.gz
cryptography-58c46c22e74e641d176537fb6cc4b593cad3e2b1.tar.bz2
cryptography-58c46c22e74e641d176537fb6cc4b593cad3e2b1.zip
Merge pull request #1384 from reaperhulk/fix-1382
enable truncation for DSA digests prior to signing
-rw-r--r--cryptography/hazmat/backends/openssl/dsa.py21
-rw-r--r--cryptography/hazmat/backends/openssl/ec.py20
-rw-r--r--cryptography/hazmat/backends/openssl/utils.py35
3 files changed, 58 insertions, 18 deletions
diff --git a/cryptography/hazmat/backends/openssl/dsa.py b/cryptography/hazmat/backends/openssl/dsa.py
index 5e7a26ff..3fb67a5d 100644
--- a/cryptography/hazmat/backends/openssl/dsa.py
+++ b/cryptography/hazmat/backends/openssl/dsa.py
@@ -15,6 +15,7 @@ from __future__ import absolute_import, division, print_function
from cryptography import utils
from cryptography.exceptions import InvalidSignature
+from cryptography.hazmat.backends.openssl.utils import _truncate_digest
from cryptography.hazmat.primitives import hashes, interfaces
from cryptography.hazmat.primitives.asymmetric import dsa
from cryptography.hazmat.primitives.interfaces import (
@@ -22,6 +23,19 @@ from cryptography.hazmat.primitives.interfaces import (
)
+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(interfaces.AsymmetricVerificationContext)
class _DSAVerificationContext(object):
def __init__(self, backend, public_key, signature, algorithm):
@@ -41,6 +55,10 @@ class _DSAVerificationContext(object):
data_to_verify = self._hash_ctx.finalize()
+ data_to_verify = _truncate_digest_for_dsa(
+ self._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(
@@ -69,6 +87,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 *")
diff --git a/cryptography/hazmat/backends/openssl/ec.py b/cryptography/hazmat/backends/openssl/ec.py
index 9371a9a9..7798c3dc 100644
--- a/cryptography/hazmat/backends/openssl/ec.py
+++ b/cryptography/hazmat/backends/openssl/ec.py
@@ -13,12 +13,11 @@
from __future__ import absolute_import, division, print_function
-import six
-
from cryptography import utils
from cryptography.exceptions import (
InvalidSignature, UnsupportedAlgorithm, _Reasons
)
+from cryptography.hazmat.backends.openssl.utils import _truncate_digest
from cryptography.hazmat.primitives import hashes, interfaces
from cryptography.hazmat.primitives.asymmetric import ec
@@ -34,8 +33,6 @@ 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:
@@ -47,20 +44,7 @@ def _truncate_digest_for_ecdsa(ec_key_cdata, digest, backend):
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):
diff --git a/cryptography/hazmat/backends/openssl/utils.py b/cryptography/hazmat/backends/openssl/utils.py
new file mode 100644
index 00000000..408b6146
--- /dev/null
+++ b/cryptography/hazmat/backends/openssl/utils.py
@@ -0,0 +1,35 @@
+# 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
+
+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 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