]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Optimise locking in rsa_get_blinding()
authorMatt Caswell <matt@openssl.org>
Fri, 12 May 2023 16:06:10 +0000 (17:06 +0100)
committerMatt Caswell <matt@openssl.org>
Tue, 30 May 2023 16:39:29 +0000 (17:39 +0100)
We optimise locking in rsa_get_blinding() so that we normally take a
read lock, and only fallback to a write lock if we need to. This will
be very slightly slower in the case of single use RSA objects, but should
be significantly better when an RSA object is reused in a multi-threaded
environment. It's probably worth the trade off.

Partially fixes #20286

Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/20953)

crypto/rsa/rsa_ossl.c

index 0dcb02bfa939d1beaffbb394b9003b8d8b32771e..8b9ebbb9ddf63d06efdd22ce447f674bd6536005 100644 (file)
@@ -186,11 +186,21 @@ static BN_BLINDING *rsa_get_blinding(RSA *rsa, int *local, BN_CTX *ctx)
 {
     BN_BLINDING *ret;
 
-    if (!CRYPTO_THREAD_write_lock(rsa->lock))
+    if (!CRYPTO_THREAD_read_lock(rsa->lock))
         return NULL;
 
     if (rsa->blinding == NULL) {
-        rsa->blinding = RSA_setup_blinding(rsa, ctx);
+        /*
+         * This dance with upgrading the lock from read to write will be
+         * slower in cases of a single use RSA object, but should be
+         * significantly better in multi-thread cases (e.g. servers). It's
+         * probably worth it.
+         */
+        CRYPTO_THREAD_unlock(rsa->lock);
+        if (!CRYPTO_THREAD_write_lock(rsa->lock))
+            return NULL;
+        if (rsa->blinding == NULL)
+            rsa->blinding = RSA_setup_blinding(rsa, ctx);
     }
 
     ret = rsa->blinding;
@@ -212,7 +222,11 @@ static BN_BLINDING *rsa_get_blinding(RSA *rsa, int *local, BN_CTX *ctx)
         *local = 0;
 
         if (rsa->mt_blinding == NULL) {
-            rsa->mt_blinding = RSA_setup_blinding(rsa, ctx);
+            CRYPTO_THREAD_unlock(rsa->lock);
+            if (!CRYPTO_THREAD_write_lock(rsa->lock))
+                return NULL;
+            if (rsa->mt_blinding == NULL)
+                rsa->mt_blinding = RSA_setup_blinding(rsa, ctx);
         }
         ret = rsa->mt_blinding;
     }