@@ -1838,54 +1838,29 @@ def dh_x942_serialization_supported(self) -> bool:
1838
1838
return self ._lib .Cryptography_HAS_EVP_PKEY_DHX == 1
1839
1839
1840
1840
def x25519_load_public_bytes (self , data : bytes ) -> x25519 .X25519PublicKey :
1841
- # If/when LibreSSL adds support for EVP_PKEY_new_raw_public_key we
1842
- # can switch to it (Cryptography_HAS_RAW_KEY)
1843
1841
if len (data ) != 32 :
1844
1842
raise ValueError ("An X25519 public key is 32 bytes long" )
1845
1843
1846
- evp_pkey = self ._create_evp_pkey_gc ()
1847
- res = self ._lib .EVP_PKEY_set_type (evp_pkey , self ._lib .NID_X25519 )
1848
- self .openssl_assert (res == 1 )
1849
- res = self ._lib .EVP_PKEY_set1_tls_encodedpoint (
1850
- evp_pkey , data , len (data )
1844
+ data_ptr = self ._ffi .from_buffer (data )
1845
+ evp_pkey = self ._lib .EVP_PKEY_new_raw_public_key (
1846
+ self ._lib .NID_X25519 , self ._ffi .NULL , data_ptr , len (data )
1851
1847
)
1852
- self .openssl_assert (res == 1 )
1848
+ self .openssl_assert (evp_pkey != self ._ffi .NULL )
1849
+ evp_pkey = self ._ffi .gc (evp_pkey , self ._lib .EVP_PKEY_free )
1853
1850
return _X25519PublicKey (self , evp_pkey )
1854
1851
1855
1852
def x25519_load_private_bytes (
1856
1853
self , data : bytes
1857
1854
) -> x25519 .X25519PrivateKey :
1858
- # If/when LibreSSL adds support for EVP_PKEY_new_raw_private_key we
1859
- # can switch to it (Cryptography_HAS_RAW_KEY) drop the
1860
- # zeroed_bytearray garbage.
1861
- # OpenSSL only has facilities for loading PKCS8 formatted private
1862
- # keys using the algorithm identifiers specified in
1863
- # https://tools.ietf.org/html/draft-ietf-curdle-pkix-09.
1864
- # This is the standard PKCS8 prefix for a 32 byte X25519 key.
1865
- # The form is:
1866
- # 0:d=0 hl=2 l= 46 cons: SEQUENCE
1867
- # 2:d=1 hl=2 l= 1 prim: INTEGER :00
1868
- # 5:d=1 hl=2 l= 5 cons: SEQUENCE
1869
- # 7:d=2 hl=2 l= 3 prim: OBJECT :1.3.101.110
1870
- # 12:d=1 hl=2 l= 34 prim: OCTET STRING (the key)
1871
- # Of course there's a bit more complexity. In reality OCTET STRING
1872
- # contains an OCTET STRING of length 32! So the last two bytes here
1873
- # are \x04\x20, which is an OCTET STRING of length 32.
1874
1855
if len (data ) != 32 :
1875
1856
raise ValueError ("An X25519 private key is 32 bytes long" )
1876
1857
1877
- pkcs8_prefix = b'0.\x02 \x01 \x00 0\x05 \x06 \x03 +en\x04 "\x04 '
1878
- with self ._zeroed_bytearray (48 ) as ba :
1879
- ba [0 :16 ] = pkcs8_prefix
1880
- ba [16 :] = data
1881
- bio = self ._bytes_to_bio (ba )
1882
- evp_pkey = self ._lib .d2i_PrivateKey_bio (bio .bio , self ._ffi .NULL )
1883
-
1858
+ data_ptr = self ._ffi .from_buffer (data )
1859
+ evp_pkey = self ._lib .EVP_PKEY_new_raw_private_key (
1860
+ self ._lib .NID_X25519 , self ._ffi .NULL , data_ptr , len (data )
1861
+ )
1884
1862
self .openssl_assert (evp_pkey != self ._ffi .NULL )
1885
1863
evp_pkey = self ._ffi .gc (evp_pkey , self ._lib .EVP_PKEY_free )
1886
- self .openssl_assert (
1887
- self ._lib .EVP_PKEY_id (evp_pkey ) == self ._lib .EVP_PKEY_X25519
1888
- )
1889
1864
return _X25519PrivateKey (self , evp_pkey )
1890
1865
1891
1866
def _evp_pkey_keygen_gc (self , nid ):
@@ -1908,7 +1883,7 @@ def x25519_generate_key(self) -> x25519.X25519PrivateKey:
1908
1883
def x25519_supported (self ) -> bool :
1909
1884
if self ._fips_enabled :
1910
1885
return False
1911
- return not self ._lib .CRYPTOGRAPHY_IS_LIBRESSL
1886
+ return not self ._lib .CRYPTOGRAPHY_LIBRESSL_LESS_THAN_370
1912
1887
1913
1888
def x448_load_public_bytes (self , data : bytes ) -> x448 .X448PublicKey :
1914
1889
if len (data ) != 56 :
@@ -2074,19 +2049,6 @@ def aead_cipher_supported(self, cipher) -> bool:
2074
2049
self ._lib .EVP_get_cipherbyname (cipher_name ) != self ._ffi .NULL
2075
2050
)
2076
2051
2077
- @contextlib .contextmanager
2078
- def _zeroed_bytearray (self , length : int ) -> typing .Iterator [bytearray ]:
2079
- """
2080
- This method creates a bytearray, which we copy data into (hopefully
2081
- also from a mutable buffer that can be dynamically erased!), and then
2082
- zero when we're done.
2083
- """
2084
- ba = bytearray (length )
2085
- try :
2086
- yield ba
2087
- finally :
2088
- self ._zero_data (ba , length )
2089
-
2090
2052
def _zero_data (self , data , length : int ) -> None :
2091
2053
# We clear things this way because at the moment we're not
2092
2054
# sure of a better way that can guarantee it overwrites the
0 commit comments