1313 */
1414#include "internal/deprecated.h"
1515
16+ #include <assert.h>
1617#include <stdio.h>
1718#include "internal/cryptlib.h"
1819#include "internal/refcount.h"
@@ -740,11 +741,8 @@ void *EVP_PKEY_get0(const EVP_PKEY *pkey)
740741{
741742 if (pkey == NULL )
742743 return NULL ;
743- if (!evp_pkey_downgrade ((EVP_PKEY * )pkey )) {
744- ERR_raise (ERR_LIB_EVP , EVP_R_INACCESSIBLE_KEY );
745- return NULL ;
746- }
747- return pkey -> pkey .ptr ;
744+
745+ return evp_pkey_get_legacy ((EVP_PKEY * )pkey );
748746}
749747
750748const unsigned char * EVP_PKEY_get0_hmac (const EVP_PKEY * pkey , size_t * len )
@@ -791,15 +789,11 @@ const unsigned char *EVP_PKEY_get0_siphash(const EVP_PKEY *pkey, size_t *len)
791789# ifndef OPENSSL_NO_DSA
792790DSA * EVP_PKEY_get0_DSA (const EVP_PKEY * pkey )
793791{
794- if (!evp_pkey_downgrade ((EVP_PKEY * )pkey )) {
795- ERR_raise (ERR_LIB_EVP , EVP_R_INACCESSIBLE_KEY );
796- return NULL ;
797- }
798792 if (pkey -> type != EVP_PKEY_DSA ) {
799793 ERR_raise (ERR_LIB_EVP , EVP_R_EXPECTING_A_DSA_KEY );
800794 return NULL ;
801795 }
802- return pkey -> pkey . dsa ;
796+ return evp_pkey_get_legacy (( EVP_PKEY * ) pkey ) ;
803797}
804798
805799int EVP_PKEY_set1_DSA (EVP_PKEY * pkey , DSA * key )
@@ -823,15 +817,11 @@ DSA *EVP_PKEY_get1_DSA(EVP_PKEY *pkey)
823817# ifndef OPENSSL_NO_EC
824818static ECX_KEY * evp_pkey_get0_ECX_KEY (const EVP_PKEY * pkey , int type )
825819{
826- if (!evp_pkey_downgrade ((EVP_PKEY * )pkey )) {
827- ERR_raise (ERR_LIB_EVP , EVP_R_INACCESSIBLE_KEY );
828- return NULL ;
829- }
830820 if (EVP_PKEY_base_id (pkey ) != type ) {
831821 ERR_raise (ERR_LIB_EVP , EVP_R_EXPECTING_A_ECX_KEY );
832822 return NULL ;
833823 }
834- return pkey -> pkey . ecx ;
824+ return evp_pkey_get_legacy (( EVP_PKEY * ) pkey ) ;
835825}
836826
837827static ECX_KEY * evp_pkey_get1_ECX_KEY (EVP_PKEY * pkey , int type )
@@ -868,15 +858,11 @@ int EVP_PKEY_set1_DH(EVP_PKEY *pkey, DH *key)
868858
869859DH * EVP_PKEY_get0_DH (const EVP_PKEY * pkey )
870860{
871- if (!evp_pkey_downgrade ((EVP_PKEY * )pkey )) {
872- ERR_raise (ERR_LIB_EVP , EVP_R_INACCESSIBLE_KEY );
873- return NULL ;
874- }
875861 if (pkey -> type != EVP_PKEY_DH && pkey -> type != EVP_PKEY_DHX ) {
876862 ERR_raise (ERR_LIB_EVP , EVP_R_EXPECTING_A_DH_KEY );
877863 return NULL ;
878864 }
879- return pkey -> pkey . dh ;
865+ return evp_pkey_get_legacy (( EVP_PKEY * ) pkey ) ;
880866}
881867
882868DH * EVP_PKEY_get1_DH (EVP_PKEY * pkey )
@@ -1310,36 +1296,6 @@ size_t EVP_PKEY_get1_encoded_public_key(EVP_PKEY *pkey, unsigned char **ppub)
13101296
13111297/*- All methods below can also be used in FIPS_MODULE */
13121298
1313- /*
1314- * This reset function must be used very carefully, as it literally throws
1315- * away everything in an EVP_PKEY without freeing them, and may cause leaks
1316- * of memory, what have you.
1317- * The only reason we have this is to have the same code for EVP_PKEY_new()
1318- * and evp_pkey_downgrade().
1319- */
1320- static int evp_pkey_reset_unlocked (EVP_PKEY * pk )
1321- {
1322- if (pk == NULL )
1323- return 0 ;
1324-
1325- if (pk -> lock != NULL ) {
1326- const size_t offset = (unsigned char * )& pk -> lock - (unsigned char * )pk ;
1327-
1328- memset (pk , 0 , offset );
1329- memset ((unsigned char * )pk + offset + sizeof (pk -> lock ),
1330- 0 ,
1331- sizeof (* pk ) - offset - sizeof (pk -> lock ));
1332- }
1333- /* EVP_PKEY_new uses zalloc so no need to call memset if pk->lock is NULL */
1334-
1335- pk -> type = EVP_PKEY_NONE ;
1336- pk -> save_type = EVP_PKEY_NONE ;
1337- pk -> references = 1 ;
1338- pk -> save_parameters = 1 ;
1339-
1340- return 1 ;
1341- }
1342-
13431299EVP_PKEY * EVP_PKEY_new (void )
13441300{
13451301 EVP_PKEY * ret = OPENSSL_zalloc (sizeof (* ret ));
@@ -1349,8 +1305,10 @@ EVP_PKEY *EVP_PKEY_new(void)
13491305 return NULL ;
13501306 }
13511307
1352- if (!evp_pkey_reset_unlocked (ret ))
1353- goto err ;
1308+ ret -> type = EVP_PKEY_NONE ;
1309+ ret -> save_type = EVP_PKEY_NONE ;
1310+ ret -> references = 1 ;
1311+ ret -> save_parameters = 1 ;
13541312
13551313 ret -> lock = CRYPTO_THREAD_lock_new ();
13561314 if (ret -> lock == NULL ) {
@@ -1559,12 +1517,32 @@ int EVP_PKEY_up_ref(EVP_PKEY *pkey)
15591517#ifndef FIPS_MODULE
15601518void evp_pkey_free_legacy (EVP_PKEY * x )
15611519{
1562- if (x -> ameth != NULL ) {
1563- if (x -> ameth -> pkey_free != NULL )
1564- x -> ameth -> pkey_free (x );
1520+ const EVP_PKEY_ASN1_METHOD * ameth = x -> ameth ;
1521+ ENGINE * tmpe = NULL ;
1522+
1523+ if (ameth == NULL && x -> legacy_cache_pkey .ptr != NULL )
1524+ ameth = EVP_PKEY_asn1_find (& tmpe , x -> type );
1525+
1526+ if (ameth != NULL ) {
1527+ if (x -> legacy_cache_pkey .ptr != NULL ) {
1528+ /*
1529+ * We should never have both a legacy origin key, and a key in the
1530+ * legacy cache.
1531+ */
1532+ assert (x -> pkey .ptr == NULL );
1533+ /*
1534+ * For the purposes of freeing we make the legacy cache look like
1535+ * a legacy origin key.
1536+ */
1537+ x -> pkey = x -> legacy_cache_pkey ;
1538+ x -> legacy_cache_pkey .ptr = NULL ;
1539+ }
1540+ if (ameth -> pkey_free != NULL )
1541+ ameth -> pkey_free (x );
15651542 x -> pkey .ptr = NULL ;
15661543 }
15671544# ifndef OPENSSL_NO_ENGINE
1545+ ENGINE_finish (tmpe );
15681546 ENGINE_finish (x -> engine );
15691547 x -> engine = NULL ;
15701548 ENGINE_finish (x -> pmeth_engine );
@@ -1877,78 +1855,57 @@ int evp_pkey_copy_downgraded(EVP_PKEY **dest, const EVP_PKEY *src)
18771855 return 0 ;
18781856}
18791857
1880- int evp_pkey_downgrade (EVP_PKEY * pk )
1858+ void * evp_pkey_get_legacy (EVP_PKEY * pk )
18811859{
1882- EVP_PKEY tmp_copy ; /* Stack allocated! */
1883- int rv = 0 ;
1860+ EVP_PKEY * tmp_copy = NULL ;
1861+ void * ret = NULL ;
18841862
18851863 if (!ossl_assert (pk != NULL ))
1886- return 0 ;
1864+ return NULL ;
18871865
18881866 /*
1889- * Throughout this whole function, we must ensure that we lock / unlock
1890- * the exact same lock. Note that we do pass it around a bit .
1867+ * If this isn't an assigned provider side key, we just use any existing
1868+ * origin legacy key .
18911869 */
1892- if (!CRYPTO_THREAD_write_lock (pk -> lock ))
1893- return 0 ;
1870+ if (!evp_pkey_is_assigned (pk ))
1871+ return NULL ;
1872+ if (!evp_pkey_is_provided (pk ))
1873+ return pk -> pkey .ptr ;
18941874
1895- /* If this isn't an assigned provider side key, we're done */
1896- if (!evp_pkey_is_assigned (pk ) || !evp_pkey_is_provided (pk )) {
1897- rv = 1 ;
1898- goto end ;
1899- }
1875+ if (!CRYPTO_THREAD_read_lock (pk -> lock ))
1876+ return NULL ;
19001877
1901- /*
1902- * To be able to downgrade, we steal the contents of |pk|, then reset
1903- * it, and finally try to make it a downgraded copy. If any of that
1904- * fails, we restore the copied contents into |pk|.
1905- */
1906- tmp_copy = * pk ; /* |tmp_copy| now owns THE lock */
1878+ ret = pk -> legacy_cache_pkey .ptr ;
19071879
1908- if (evp_pkey_reset_unlocked (pk )
1909- && evp_pkey_copy_downgraded ( & pk , & tmp_copy )) {
1880+ if (! CRYPTO_THREAD_unlock (pk -> lock ) )
1881+ return NULL ;
19101882
1911- /* Restore the common attributes, then empty |tmp_copy| */
1912- pk -> references = tmp_copy .references ;
1913- pk -> attributes = tmp_copy .attributes ;
1914- pk -> save_parameters = tmp_copy .save_parameters ;
1915- pk -> ex_data = tmp_copy .ex_data ;
1883+ if (ret != NULL )
1884+ return ret ;
19161885
1917- /* Ensure that stuff we've copied won't be freed */
1918- tmp_copy .lock = NULL ;
1919- tmp_copy .attributes = NULL ;
1920- memset (& tmp_copy .ex_data , 0 , sizeof (tmp_copy .ex_data ));
1886+ if (!evp_pkey_copy_downgraded (& tmp_copy , pk ))
1887+ return NULL ;
19211888
1922- /*
1923- * Save the provider side data in the operation cache, so they'll
1924- * find it again. |pk| is new, so it's safe to assume slot zero
1925- * is free.
1926- * Note that evp_keymgmt_util_cache_keydata() increments keymgmt's
1927- * reference count, so we need to decrement it, or there will be a
1928- * leak.
1929- */
1930- evp_keymgmt_util_cache_keydata (pk , tmp_copy .keymgmt ,
1931- tmp_copy .keydata );
1932- EVP_KEYMGMT_free (tmp_copy .keymgmt );
1889+ if (!CRYPTO_THREAD_write_lock (pk -> lock ))
1890+ goto err ;
19331891
1934- /*
1935- * Clear keymgmt and keydata from |tmp_copy|, or they'll get
1936- * inadvertently freed.
1937- */
1938- tmp_copy .keymgmt = NULL ;
1939- tmp_copy .keydata = NULL ;
1892+ /* Check again in case some other thread has updated it in the meantime */
1893+ ret = pk -> legacy_cache_pkey .ptr ;
1894+ if (ret == NULL ) {
1895+ /* Steal the legacy key reference from the temporary copy */
1896+ ret = pk -> legacy_cache_pkey .ptr = tmp_copy -> pkey .ptr ;
1897+ tmp_copy -> pkey .ptr = NULL ;
1898+ }
19401899
1941- evp_pkey_free_it (& tmp_copy );
1942- rv = 1 ;
1943- } else {
1944- /* Restore the original key */
1945- * pk = tmp_copy ;
1900+ if (!CRYPTO_THREAD_unlock (pk -> lock )) {
1901+ ret = NULL ;
1902+ goto err ;
19461903 }
19471904
1948- end :
1949- if (! CRYPTO_THREAD_unlock ( pk -> lock ))
1950- return 0 ;
1951- return rv ;
1905+ err :
1906+ EVP_PKEY_free ( tmp_copy );
1907+
1908+ return ret ;
19521909}
19531910#endif /* FIPS_MODULE */
19541911
0 commit comments