Skip to content

Commit

Permalink
Port DSA to Rust (#8978)
Browse files Browse the repository at this point in the history
  • Loading branch information
alex committed May 30, 2023
1 parent f302d28 commit 91e4189
Show file tree
Hide file tree
Showing 20 changed files with 445 additions and 364 deletions.
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

0 comments on commit 91e4189

Please sign in to comment.