mirror of
https://github.com/saymrwulf/cryptography.git
synced 2026-05-14 20:37:55 +00:00
RSA OAEP label support for OpenSSL 1.0.2+ (#3897)
* RSA OAEP label support for OpenSSL 1.0.2+ * changelog * move around tests, address review feedback, use backend supported method * unsupported padding catches this now
This commit is contained in:
parent
52067bc300
commit
d4bde9ce66
5 changed files with 153 additions and 18 deletions
|
|
@ -38,6 +38,10 @@ Changelog
|
|||
* Support :class:`~cryptography.hazmat.primitives.hashes.BLAKE2b` and
|
||||
:class:`~cryptography.hazmat.primitives.hashes.BLAKE2s` with
|
||||
:class:`~cryptography.hazmat.primitives.hmac.HMAC`.
|
||||
* Added support for using labels with
|
||||
:class:`~cryptography.hazmat.primitives.asymmetric.padding.OAEP` when using
|
||||
OpenSSL 1.0.2 or greater.
|
||||
|
||||
|
||||
|
||||
.. _v2-0-3:
|
||||
|
|
|
|||
|
|
@ -547,7 +547,11 @@ class Backend(object):
|
|||
elif isinstance(padding, OAEP) and isinstance(padding._mgf, MGF1):
|
||||
return (
|
||||
self._oaep_hash_supported(padding._mgf._algorithm) and
|
||||
self._oaep_hash_supported(padding._algorithm)
|
||||
self._oaep_hash_supported(padding._algorithm) and
|
||||
(
|
||||
(padding._label is None or len(padding._label) == 0) or
|
||||
self._lib.Cryptography_HAS_RSA_OAEP_LABEL == 1
|
||||
)
|
||||
)
|
||||
else:
|
||||
return False
|
||||
|
|
|
|||
|
|
@ -57,9 +57,6 @@ def _enc_dec_rsa(backend, key, data, padding):
|
|||
_Reasons.UNSUPPORTED_PADDING
|
||||
)
|
||||
|
||||
if padding._label is not None and padding._label != b"":
|
||||
raise ValueError("This backend does not support OAEP labels.")
|
||||
|
||||
else:
|
||||
raise UnsupportedAlgorithm(
|
||||
"{0} is not supported by this backend.".format(
|
||||
|
|
@ -106,6 +103,21 @@ def _enc_dec_rsa_pkey_ctx(backend, key, data, padding_enum, padding):
|
|||
res = backend._lib.EVP_PKEY_CTX_set_rsa_oaep_md(pkey_ctx, oaep_md)
|
||||
backend.openssl_assert(res > 0)
|
||||
|
||||
if (
|
||||
isinstance(padding, OAEP) and
|
||||
padding._label is not None and
|
||||
len(padding._label) > 0
|
||||
):
|
||||
# set0_rsa_oaep_label takes ownership of the char * so we need to
|
||||
# copy it into some new memory
|
||||
labelptr = backend._lib.OPENSSL_malloc(len(padding._label))
|
||||
backend.openssl_assert(labelptr != backend._ffi.NULL)
|
||||
backend._ffi.memmove(labelptr, padding._label, len(padding._label))
|
||||
res = backend._lib.EVP_PKEY_CTX_set0_rsa_oaep_label(
|
||||
pkey_ctx, labelptr, len(padding._label)
|
||||
)
|
||||
backend.openssl_assert(res == 1)
|
||||
|
||||
outlen = backend._ffi.new("size_t *", buf_size)
|
||||
buf = backend._ffi.new("unsigned char[]", buf_size)
|
||||
res = crypt(pkey_ctx, buf, outlen, data, len(data))
|
||||
|
|
|
|||
|
|
@ -422,18 +422,6 @@ class TestOpenSSLRSA(object):
|
|||
)
|
||||
)
|
||||
|
||||
def test_unsupported_oaep_label_decrypt(self):
|
||||
private_key = RSA_KEY_512.private_key(backend)
|
||||
with pytest.raises(ValueError):
|
||||
private_key.decrypt(
|
||||
b"0" * 64,
|
||||
padding.OAEP(
|
||||
mgf=padding.MGF1(algorithm=hashes.SHA1()),
|
||||
algorithm=hashes.SHA1(),
|
||||
label=b"label"
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class TestOpenSSLCMAC(object):
|
||||
def test_unsupported_cipher(self):
|
||||
|
|
|
|||
|
|
@ -38,8 +38,8 @@ from ...doubles import (
|
|||
DummyAsymmetricPadding, DummyHashAlgorithm, DummyKeySerializationEncryption
|
||||
)
|
||||
from ...utils import (
|
||||
load_pkcs1_vectors, load_rsa_nist_vectors, load_vectors_from_file,
|
||||
raises_unsupported_algorithm
|
||||
load_nist_vectors, load_pkcs1_vectors, load_rsa_nist_vectors,
|
||||
load_vectors_from_file, raises_unsupported_algorithm
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -218,6 +218,133 @@ class TestRSA(object):
|
|||
assert public_num.n == public_num2.n
|
||||
assert public_num.e == public_num2.e
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"vector",
|
||||
load_vectors_from_file(
|
||||
os.path.join("asymmetric", "RSA", "oaep-label.txt"),
|
||||
load_nist_vectors)
|
||||
)
|
||||
@pytest.mark.supported(
|
||||
only_if=lambda backend: backend.rsa_padding_supported(
|
||||
padding.OAEP(
|
||||
mgf=padding.MGF1(algorithm=hashes.SHA256()),
|
||||
algorithm=hashes.SHA256(),
|
||||
label=b"label"
|
||||
)
|
||||
),
|
||||
skip_message="Does not support RSA OAEP labels"
|
||||
)
|
||||
def test_oaep_label_decrypt(self, vector, backend):
|
||||
private_key = serialization.load_der_private_key(
|
||||
binascii.unhexlify(vector["key"]), None, backend
|
||||
)
|
||||
assert vector["oaepdigest"] == b"SHA512"
|
||||
decrypted = private_key.decrypt(
|
||||
binascii.unhexlify(vector["input"]),
|
||||
padding.OAEP(
|
||||
mgf=padding.MGF1(algorithm=hashes.SHA512()),
|
||||
algorithm=hashes.SHA512(),
|
||||
label=binascii.unhexlify(vector["oaeplabel"])
|
||||
)
|
||||
)
|
||||
assert vector["output"][1:-1] == decrypted
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("msg", "label"),
|
||||
[
|
||||
(b"amazing encrypted msg", b"some label"),
|
||||
(b"amazing encrypted msg", b""),
|
||||
]
|
||||
)
|
||||
@pytest.mark.supported(
|
||||
only_if=lambda backend: backend.rsa_padding_supported(
|
||||
padding.OAEP(
|
||||
mgf=padding.MGF1(algorithm=hashes.SHA256()),
|
||||
algorithm=hashes.SHA256(),
|
||||
label=b"label"
|
||||
)
|
||||
),
|
||||
skip_message="Does not support RSA OAEP labels"
|
||||
)
|
||||
def test_oaep_label_roundtrip(self, msg, label, backend):
|
||||
private_key = RSA_KEY_2048.private_key(backend)
|
||||
ct = private_key.public_key().encrypt(
|
||||
msg,
|
||||
padding.OAEP(
|
||||
mgf=padding.MGF1(algorithm=hashes.SHA256()),
|
||||
algorithm=hashes.SHA256(),
|
||||
label=label
|
||||
)
|
||||
)
|
||||
pt = private_key.decrypt(
|
||||
ct,
|
||||
padding.OAEP(
|
||||
mgf=padding.MGF1(algorithm=hashes.SHA256()),
|
||||
algorithm=hashes.SHA256(),
|
||||
label=label
|
||||
)
|
||||
)
|
||||
assert pt == msg
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("enclabel", "declabel"),
|
||||
[
|
||||
(b"label1", b"label2"),
|
||||
(b"label3", b""),
|
||||
(b"", b"label4"),
|
||||
]
|
||||
)
|
||||
@pytest.mark.supported(
|
||||
only_if=lambda backend: backend.rsa_padding_supported(
|
||||
padding.OAEP(
|
||||
mgf=padding.MGF1(algorithm=hashes.SHA256()),
|
||||
algorithm=hashes.SHA256(),
|
||||
label=b"label"
|
||||
)
|
||||
),
|
||||
skip_message="Does not support RSA OAEP labels"
|
||||
)
|
||||
def test_oaep_wrong_label(self, enclabel, declabel, backend):
|
||||
private_key = RSA_KEY_2048.private_key(backend)
|
||||
msg = b"test"
|
||||
ct = private_key.public_key().encrypt(
|
||||
msg, padding.OAEP(
|
||||
mgf=padding.MGF1(algorithm=hashes.SHA256()),
|
||||
algorithm=hashes.SHA256(),
|
||||
label=enclabel
|
||||
)
|
||||
)
|
||||
with pytest.raises(ValueError):
|
||||
private_key.decrypt(
|
||||
ct, padding.OAEP(
|
||||
mgf=padding.MGF1(algorithm=hashes.SHA256()),
|
||||
algorithm=hashes.SHA256(),
|
||||
label=declabel
|
||||
)
|
||||
)
|
||||
|
||||
@pytest.mark.supported(
|
||||
only_if=lambda backend: not backend.rsa_padding_supported(
|
||||
padding.OAEP(
|
||||
mgf=padding.MGF1(algorithm=hashes.SHA256()),
|
||||
algorithm=hashes.SHA256(),
|
||||
label=b"label"
|
||||
)
|
||||
),
|
||||
skip_message="Requires backend without RSA OAEP label support"
|
||||
)
|
||||
def test_unsupported_oaep_label_decrypt(self, backend):
|
||||
private_key = RSA_KEY_512.private_key(backend)
|
||||
with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_PADDING):
|
||||
private_key.decrypt(
|
||||
b"0" * 64,
|
||||
padding.OAEP(
|
||||
mgf=padding.MGF1(algorithm=hashes.SHA1()),
|
||||
algorithm=hashes.SHA1(),
|
||||
label=b"label"
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_rsa_generate_invalid_backend():
|
||||
pretend_backend = object()
|
||||
|
|
|
|||
Loading…
Reference in a new issue