Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Port DSA to Rust #8978

Merged
merged 1 commit into from May 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 0 additions & 2 deletions src/_cffi_src/openssl/bignum.py
Expand Up @@ -39,8 +39,6 @@
int BN_MONT_CTX_set(BN_MONT_CTX *, const BIGNUM *, BN_CTX *);
void BN_MONT_CTX_free(BN_MONT_CTX *);
BIGNUM *BN_dup(const BIGNUM *);
int BN_set_word(BIGNUM *, BN_ULONG);
char *BN_bn2hex(const BIGNUM *);
Expand Down
3 changes: 0 additions & 3 deletions src/_cffi_src/openssl/dsa.py
Expand Up @@ -23,10 +23,7 @@
int DSA_verify(int, const unsigned char *, int, const unsigned char *, int,
DSA *);
void DSA_get0_pqg(const DSA *, const BIGNUM **, const BIGNUM **,
const BIGNUM **);
int DSA_set0_pqg(DSA *, BIGNUM *, BIGNUM *, BIGNUM *);
void DSA_get0_key(const DSA *, const BIGNUM **, const BIGNUM **);
int DSA_set0_key(DSA *, BIGNUM *, BIGNUM *);
int DSA_generate_parameters_ex(DSA *, int, unsigned char *, int,
int *, unsigned long *, BN_GENCB *);
Expand Down
1 change: 0 additions & 1 deletion src/_cffi_src/openssl/evp.py
Expand Up @@ -66,7 +66,6 @@
int EVP_PKEY_type(int);
int EVP_PKEY_size(EVP_PKEY *);
RSA *EVP_PKEY_get1_RSA(EVP_PKEY *);
DSA *EVP_PKEY_get1_DSA(EVP_PKEY *);
int EVP_PKEY_encrypt(EVP_PKEY_CTX *, unsigned char *, size_t *,
const unsigned char *, size_t);
Expand Down
117 changes: 16 additions & 101 deletions src/cryptography/hazmat/backends/openssl/backend.py
Expand Up @@ -15,11 +15,6 @@
from cryptography.hazmat.backends.openssl import aead
from cryptography.hazmat.backends.openssl.ciphers import _CipherContext
from cryptography.hazmat.backends.openssl.cmac import _CMACContext
from cryptography.hazmat.backends.openssl.dsa import (
_DSAParameters,
_DSAPrivateKey,
_DSAPublicKey,
)
from cryptography.hazmat.backends.openssl.ec import (
_EllipticCurvePrivateKey,
_EllipticCurvePublicKey,
Expand Down Expand Up @@ -551,10 +546,9 @@ def _evp_pkey_to_private_key(
unsafe_skip_rsa_key_validation=unsafe_skip_rsa_key_validation,
)
elif key_type == self._lib.EVP_PKEY_DSA:
dsa_cdata = self._lib.EVP_PKEY_get1_DSA(evp_pkey)
self.openssl_assert(dsa_cdata != self._ffi.NULL)
dsa_cdata = self._ffi.gc(dsa_cdata, self._lib.DSA_free)
return _DSAPrivateKey(self, dsa_cdata, evp_pkey)
return rust_openssl.dsa.private_key_from_ptr(
int(self._ffi.cast("uintptr_t", evp_pkey))
)
elif key_type == self._lib.EVP_PKEY_EC:
ec_cdata = self._lib.EVP_PKEY_get1_EC_KEY(evp_pkey)
self.openssl_assert(ec_cdata != self._ffi.NULL)
Expand Down Expand Up @@ -613,10 +607,9 @@ def _evp_pkey_to_public_key(self, evp_pkey) -> PublicKeyTypes:
self.openssl_assert(res == 1)
return self.load_der_public_key(self._read_mem_bio(bio))
elif key_type == self._lib.EVP_PKEY_DSA:
dsa_cdata = self._lib.EVP_PKEY_get1_DSA(evp_pkey)
self.openssl_assert(dsa_cdata != self._ffi.NULL)
dsa_cdata = self._ffi.gc(dsa_cdata, self._lib.DSA_free)
return _DSAPublicKey(self, dsa_cdata, evp_pkey)
return rust_openssl.dsa.public_key_from_ptr(
int(self._ffi.cast("uintptr_t", evp_pkey))
)
elif key_type == self._lib.EVP_PKEY_EC:
ec_cdata = self._lib.EVP_PKEY_get1_EC_KEY(evp_pkey)
if ec_cdata == self._ffi.NULL:
Expand Down Expand Up @@ -696,115 +689,41 @@ def generate_dsa_parameters(self, key_size: int) -> dsa.DSAParameters:
"Key size must be 1024, 2048, 3072, or 4096 bits."
)

ctx = self._lib.DSA_new()
self.openssl_assert(ctx != self._ffi.NULL)
ctx = self._ffi.gc(ctx, self._lib.DSA_free)

res = self._lib.DSA_generate_parameters_ex(
ctx,
key_size,
self._ffi.NULL,
0,
self._ffi.NULL,
self._ffi.NULL,
self._ffi.NULL,
)

self.openssl_assert(res == 1)

return _DSAParameters(self, ctx)
return rust_openssl.dsa.generate_parameters(key_size)

def generate_dsa_private_key(
self, parameters: dsa.DSAParameters
) -> dsa.DSAPrivateKey:
ctx = self._lib.DSAparams_dup(
parameters._dsa_cdata # type: ignore[attr-defined]
)
self.openssl_assert(ctx != self._ffi.NULL)
ctx = self._ffi.gc(ctx, self._lib.DSA_free)
self._lib.DSA_generate_key(ctx)
evp_pkey = self._dsa_cdata_to_evp_pkey(ctx)

return _DSAPrivateKey(self, ctx, evp_pkey)
return parameters.generate_private_key()

def generate_dsa_private_key_and_parameters(
self, key_size: int
) -> dsa.DSAPrivateKey:
parameters = self.generate_dsa_parameters(key_size)
return self.generate_dsa_private_key(parameters)

def _dsa_cdata_set_values(
self, dsa_cdata, p, q, g, pub_key, priv_key
) -> None:
res = self._lib.DSA_set0_pqg(dsa_cdata, p, q, g)
self.openssl_assert(res == 1)
res = self._lib.DSA_set0_key(dsa_cdata, pub_key, priv_key)
self.openssl_assert(res == 1)

def load_dsa_private_numbers(
self, numbers: dsa.DSAPrivateNumbers
) -> dsa.DSAPrivateKey:
dsa._check_dsa_private_numbers(numbers)
parameter_numbers = numbers.public_numbers.parameter_numbers

dsa_cdata = self._lib.DSA_new()
self.openssl_assert(dsa_cdata != self._ffi.NULL)
dsa_cdata = self._ffi.gc(dsa_cdata, self._lib.DSA_free)

p = self._int_to_bn(parameter_numbers.p)
q = self._int_to_bn(parameter_numbers.q)
g = self._int_to_bn(parameter_numbers.g)
pub_key = self._int_to_bn(numbers.public_numbers.y)
priv_key = self._int_to_bn(numbers.x)
self._dsa_cdata_set_values(dsa_cdata, p, q, g, pub_key, priv_key)

evp_pkey = self._dsa_cdata_to_evp_pkey(dsa_cdata)

return _DSAPrivateKey(self, dsa_cdata, evp_pkey)
return rust_openssl.dsa.from_private_numbers(numbers)

def load_dsa_public_numbers(
self, numbers: dsa.DSAPublicNumbers
) -> dsa.DSAPublicKey:
dsa._check_dsa_parameters(numbers.parameter_numbers)
dsa_cdata = self._lib.DSA_new()
self.openssl_assert(dsa_cdata != self._ffi.NULL)
dsa_cdata = self._ffi.gc(dsa_cdata, self._lib.DSA_free)

p = self._int_to_bn(numbers.parameter_numbers.p)
q = self._int_to_bn(numbers.parameter_numbers.q)
g = self._int_to_bn(numbers.parameter_numbers.g)
pub_key = self._int_to_bn(numbers.y)
priv_key = self._ffi.NULL
self._dsa_cdata_set_values(dsa_cdata, p, q, g, pub_key, priv_key)

evp_pkey = self._dsa_cdata_to_evp_pkey(dsa_cdata)

return _DSAPublicKey(self, dsa_cdata, evp_pkey)
return rust_openssl.dsa.from_public_numbers(numbers)

def load_dsa_parameter_numbers(
self, numbers: dsa.DSAParameterNumbers
) -> dsa.DSAParameters:
dsa._check_dsa_parameters(numbers)
dsa_cdata = self._lib.DSA_new()
self.openssl_assert(dsa_cdata != self._ffi.NULL)
dsa_cdata = self._ffi.gc(dsa_cdata, self._lib.DSA_free)

p = self._int_to_bn(numbers.p)
q = self._int_to_bn(numbers.q)
g = self._int_to_bn(numbers.g)
res = self._lib.DSA_set0_pqg(dsa_cdata, p, q, g)
self.openssl_assert(res == 1)

return _DSAParameters(self, dsa_cdata)

def _dsa_cdata_to_evp_pkey(self, dsa_cdata):
evp_pkey = self._create_evp_pkey_gc()
res = self._lib.EVP_PKEY_set1_DSA(evp_pkey, dsa_cdata)
self.openssl_assert(res == 1)
return evp_pkey
return rust_openssl.dsa.from_parameter_numbers(numbers)

def dsa_supported(self) -> bool:
return not self._fips_enabled
return (
not self._lib.CRYPTOGRAPHY_IS_BORINGSSL and not self._fips_enabled
)

def dsa_hash_supported(self, algorithm: hashes.HashAlgorithm) -> bool:
if not self.dsa_supported():
Expand Down Expand Up @@ -1409,8 +1328,6 @@ def _private_key_bytes(
if encoding is serialization.Encoding.PEM:
if key_type == self._lib.EVP_PKEY_RSA:
write_bio = self._lib.PEM_write_bio_RSAPrivateKey
elif key_type == self._lib.EVP_PKEY_DSA:
write_bio = self._lib.PEM_write_bio_DSAPrivateKey
else:
assert key_type == self._lib.EVP_PKEY_EC
write_bio = self._lib.PEM_write_bio_ECPrivateKey
Expand All @@ -1426,11 +1343,9 @@ def _private_key_bytes(
)
if key_type == self._lib.EVP_PKEY_RSA:
write_bio = self._lib.i2d_RSAPrivateKey_bio
elif key_type == self._lib.EVP_PKEY_EC:
write_bio = self._lib.i2d_ECPrivateKey_bio
else:
assert key_type == self._lib.EVP_PKEY_DSA
write_bio = self._lib.i2d_DSAPrivateKey_bio
assert key_type == self._lib.EVP_PKEY_EC
write_bio = self._lib.i2d_ECPrivateKey_bio
return self._bio_func_output(write_bio, cdata)

raise ValueError("Unsupported encoding for TraditionalOpenSSL")
Expand Down