aboutsummaryrefslogtreecommitdiffstats
path: root/cryptography
diff options
context:
space:
mode:
authorAlex Gaynor <alex.gaynor@gmail.com>2014-03-17 20:50:03 -0700
committerAlex Gaynor <alex.gaynor@gmail.com>2014-03-17 20:50:03 -0700
commit38c42635490d24d7ee88041b52002156c6f5a676 (patch)
tree34606dbe780ec7704051f26b0f12ab8755fca812 /cryptography
parent0380374fdae7bd744e46ad526af721fae11aa475 (diff)
parenta38e8e580c09cebcab528be7e806f63539498f94 (diff)
downloadcryptography-38c42635490d24d7ee88041b52002156c6f5a676.tar.gz
cryptography-38c42635490d24d7ee88041b52002156c6f5a676.tar.bz2
cryptography-38c42635490d24d7ee88041b52002156c6f5a676.zip
Merge pull request #792 from reaperhulk/rsa-pss-verify
RSA PSS Verify
Diffstat (limited to 'cryptography')
-rw-r--r--cryptography/hazmat/backends/openssl/backend.py84
-rw-r--r--cryptography/hazmat/primitives/asymmetric/padding.py8
2 files changed, 90 insertions, 2 deletions
diff --git a/cryptography/hazmat/backends/openssl/backend.py b/cryptography/hazmat/backends/openssl/backend.py
index b977b4c8..7c058f58 100644
--- a/cryptography/hazmat/backends/openssl/backend.py
+++ b/cryptography/hazmat/backends/openssl/backend.py
@@ -21,7 +21,7 @@ import six
from cryptography import utils
from cryptography.exceptions import (
InvalidTag, InternalError, AlreadyFinalized, UnsupportedCipher,
- UnsupportedHash, UnsupportedPadding, InvalidSignature
+ UnsupportedAlgorithm, UnsupportedHash, UnsupportedPadding, InvalidSignature
)
from cryptography.hazmat.backends.interfaces import (
CipherBackend, HashBackend, HMACBackend, PBKDF2HMACBackend, RSABackend
@@ -29,6 +29,9 @@ from cryptography.hazmat.backends.interfaces import (
from cryptography.hazmat.bindings.openssl.binding import Binding
from cryptography.hazmat.primitives import interfaces, hashes
from cryptography.hazmat.primitives.asymmetric import rsa
+from cryptography.hazmat.primitives.asymmetric.padding import (
+ PKCS1v15, PSS, MGF1
+)
from cryptography.hazmat.primitives.ciphers.algorithms import (
AES, Blowfish, Camellia, CAST5, TripleDES, ARC4, IDEA
)
@@ -404,6 +407,12 @@ class Backend(object):
return _RSAVerificationContext(self, public_key, signature, padding,
algorithm)
+ def mgf1_hash_supported(self, algorithm):
+ if self._lib.Cryptography_HAS_MGF1_MD:
+ return self.hash_supported(algorithm)
+ else:
+ return isinstance(algorithm, hashes.SHA1)
+
class GetCipherByName(object):
def __init__(self, fmt):
@@ -787,12 +796,29 @@ class _RSAVerificationContext(object):
raise TypeError(
"Expected provider of interfaces.AsymmetricPadding")
- if padding.name == "EMSA-PKCS1-v1_5":
+ if isinstance(padding, PKCS1v15):
if self._backend._lib.Cryptography_HAS_PKEY_CTX:
self._verify_method = self._verify_pkey_ctx
self._padding_enum = self._backend._lib.RSA_PKCS1_PADDING
else:
self._verify_method = self._verify_pkcs1
+ elif isinstance(padding, PSS):
+ if not isinstance(padding._mgf, MGF1):
+ raise UnsupportedAlgorithm(
+ "Only MGF1 is supported by this backend"
+ )
+
+ if not self._backend.mgf1_hash_supported(padding._mgf._algorithm):
+ raise UnsupportedHash(
+ "When OpenSSL is older than 1.0.1 then only SHA1 is "
+ "supported with MGF1."
+ )
+
+ if self._backend._lib.Cryptography_HAS_PKEY_CTX:
+ self._verify_method = self._verify_pkey_ctx
+ self._padding_enum = self._backend._lib.RSA_PKCS1_PSS_PADDING
+ else:
+ self._verify_method = self._verify_pss
else:
raise UnsupportedPadding
@@ -833,6 +859,20 @@ class _RSAVerificationContext(object):
res = self._backend._lib.EVP_PKEY_CTX_set_rsa_padding(
pkey_ctx, self._padding_enum)
assert res > 0
+ if isinstance(self._padding, PSS):
+ res = self._backend._lib.EVP_PKEY_CTX_set_rsa_pss_saltlen(
+ pkey_ctx, self._get_salt_length())
+ 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
+ res = self._backend._lib.EVP_PKEY_CTX_set_rsa_mgf1_md(
+ pkey_ctx, mgf1_md
+ )
+ assert res > 0
+
data_to_verify = self._hash_ctx.finalize()
self._hash_ctx = None
res = self._backend._lib.EVP_PKEY_verify(
@@ -869,5 +909,45 @@ class _RSAVerificationContext(object):
assert errors
raise InvalidSignature
+ def _verify_pss(self, evp_pkey, evp_md):
+ pkey_size = self._backend._lib.EVP_PKEY_size(evp_pkey)
+ assert pkey_size > 0
+ rsa_cdata = self._backend._lib.EVP_PKEY_get1_RSA(evp_pkey)
+ assert rsa_cdata != self._backend._ffi.NULL
+ rsa_cdata = self._backend._ffi.gc(rsa_cdata,
+ self._backend._lib.RSA_free)
+ buf = self._backend._ffi.new("unsigned char[]", pkey_size)
+ res = self._backend._lib.RSA_public_decrypt(
+ len(self._signature),
+ self._signature,
+ buf,
+ rsa_cdata,
+ self._backend._lib.RSA_NO_PADDING
+ )
+ if res != pkey_size:
+ errors = self._backend._consume_errors()
+ assert errors
+ raise InvalidSignature
+
+ data_to_verify = self._hash_ctx.finalize()
+ self._hash_ctx = None
+ res = self._backend._lib.RSA_verify_PKCS1_PSS(
+ rsa_cdata,
+ data_to_verify,
+ evp_md,
+ buf,
+ self._get_salt_length()
+ )
+ if res != 1:
+ errors = self._backend._consume_errors()
+ assert errors
+ raise InvalidSignature
+
+ def _get_salt_length(self):
+ if self._padding._mgf._salt_length is MGF1.MAX_LENGTH:
+ return -2
+ else:
+ return self._padding._mgf._salt_length
+
backend = Backend()
diff --git a/cryptography/hazmat/primitives/asymmetric/padding.py b/cryptography/hazmat/primitives/asymmetric/padding.py
index 46e00b8e..02aff280 100644
--- a/cryptography/hazmat/primitives/asymmetric/padding.py
+++ b/cryptography/hazmat/primitives/asymmetric/padding.py
@@ -24,6 +24,14 @@ class PKCS1v15(object):
name = "EMSA-PKCS1-v1_5"
+@utils.register_interface(interfaces.AsymmetricPadding)
+class PSS(object):
+ name = "EMSA-PSS"
+
+ def __init__(self, mgf):
+ self._mgf = mgf
+
+
class MGF1(object):
MAX_LENGTH = object()