aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Kehrer <paul.l.kehrer@gmail.com>2014-10-02 16:38:44 -0500
committerPaul Kehrer <paul.l.kehrer@gmail.com>2014-10-03 14:46:59 -0500
commitf80e28767f60f90b6f0caa0c0dca17accf99ce71 (patch)
tree9fe32e96ba53fac41e8263d3585c8d26b0c276e1
parenta7165c4250ce523f240638549141bd1073fc9c21 (diff)
downloadcryptography-f80e28767f60f90b6f0caa0c0dca17accf99ce71.tar.gz
cryptography-f80e28767f60f90b6f0caa0c0dca17accf99ce71.tar.bz2
cryptography-f80e28767f60f90b6f0caa0c0dca17accf99ce71.zip
enable truncation for DSA digests prior to signing
This works around a bug in OpenSSL 1.0.0, 1.0.0a, and 1.0.0b where SHA-2 is a supported signature algorithm but FIPS 186-3 truncation is not performed if the q value is smaller than the digest output length
-rw-r--r--cryptography/hazmat/backends/openssl/dsa.py20
-rw-r--r--cryptography/hazmat/backends/openssl/ec.py20
2 files changed, 22 insertions, 18 deletions
diff --git a/cryptography/hazmat/backends/openssl/dsa.py b/cryptography/hazmat/backends/openssl/dsa.py
index 5e7a26ff..4b5ca59c 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,18 @@ 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.
+ """
+
+ 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 +54,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 +86,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):