Improve the RSA PSS code.

- sign_pss and verify_pss need to digest the data before calling into their
respective wolfCrypt functions. Those wolfCrypt functions expect digests, not
plaintext.
- RsaPrivate make_key should take an optional hash_type parameter for the case
where the key will be used to create PSS signatures.
- test_rsa_pss_sign_verify appears to have been deliberately coded to have the
input plaintext length line up with the digest size, which masked the problem
where we weren't digesting the plaintext. I modified the plaintext so that this
is no longer the case.
pull/50/head
Hayden Roche 2022-10-11 15:55:41 -07:00
parent bf0a4c2425
commit 769fba80b6
3 changed files with 41 additions and 5 deletions

View File

@ -450,7 +450,7 @@ if _lib.RSA_ENABLED:
if _lib.RSA_PSS_ENABLED:
def test_rsa_pss_sign_verify(rsa_private_pss, rsa_public_pss):
plaintext = t2b("Everyone gets Friday off yippee.")
plaintext = t2b("Everyone gets Friday off.")
# normal usage, sign with private, verify with public
signature = rsa_private_pss.sign_pss(plaintext)

View File

@ -25,6 +25,7 @@ from wolfcrypt._ffi import lib as _lib
from wolfcrypt.utils import t2b
from wolfcrypt.random import Random
from wolfcrypt.asn import pem_to_der
from wolfcrypt.hashes import hash_type_to_cls
from wolfcrypt.exceptions import WolfCryptError
@ -597,6 +598,14 @@ if _lib.RSA_ENABLED:
Returns a string containing the plaintext.
"""
if not self._hash_type:
raise WolfCryptError(("Hash type not set. Cannot verify a "
"PSS signature without a hash type."))
hash_cls = hash_type_to_cls(self._hash_type)
if not hash_cls:
raise WolfCryptError("Unsupported PSS hash type.")
plaintext = t2b(plaintext)
signature = t2b(signature)
if self._mgf is None:
@ -610,7 +619,9 @@ if _lib.RSA_ENABLED:
if ret < 0: # pragma: no cover
raise WolfCryptError("Verify error (%d)" % ret)
ret = _lib.wc_RsaPSS_CheckPadding(plaintext, len(plaintext),
digest = hash_cls.new(plaintext).digest()
ret = _lib.wc_RsaPSS_CheckPadding(digest, len(digest),
verify, ret, self._hash_type)
return ret
@ -620,11 +631,11 @@ if _lib.RSA_ENABLED:
class RsaPrivate(RsaPublic):
if _lib.KEYGEN_ENABLED:
@classmethod
def make_key(cls, size, rng=Random()):
def make_key(cls, size, rng=Random(), hash_type=None):
"""
Generates a new key pair of desired length **size**.
"""
rsa = cls(None)
rsa = cls(hash_type=hash_type)
if rsa == None: # pragma: no cover
raise WolfCryptError("Invalid key error (%d)" % ret)
@ -776,11 +787,22 @@ if _lib.RSA_ENABLED:
Returns a string containing the signature.
"""
if not self._hash_type:
raise WolfCryptError(("Hash type not set. Cannot verify a "
"PSS signature without a hash type."))
hash_cls = hash_type_to_cls(self._hash_type)
if not hash_cls:
raise WolfCryptError("Unsupported PSS hash type.")
plaintext = t2b(plaintext)
digest = hash_cls.new(plaintext).digest()
signature = _ffi.new("byte[%d]" % self.output_size)
if self._mgf is None:
self._get_mgf()
ret = _lib.wc_RsaPSS_Sign(plaintext, len(plaintext),
ret = _lib.wc_RsaPSS_Sign(digest, len(digest),
signature, self.output_size,
self._hash_type, self._mgf,
self.native_object,

View File

@ -377,3 +377,17 @@ if _lib.HMAC_ENABLED:
"""
_type = _TYPE_SHA512
digest_size = Sha512.digest_size
def hash_type_to_cls(hash_type):
if _lib.SHA_ENABLED and hash_type == _lib.WC_HASH_TYPE_SHA:
hash_cls = Sha
elif _lib.SHA256_ENABLED and hash_type == _lib.WC_HASH_TYPE_SHA256:
hash_cls = Sha256
elif _lib.SHA384_ENABLED and hash_type == _lib.WC_HASH_TYPE_SHA384:
hash_cls = Sha384
elif _lib.SHA512_ENABLED and hash_type == _lib.WC_HASH_TYPE_SHA512:
hash_cls = Sha512
else:
hash_cls = None
return hash_cls