#include "internal/cryptlib.h"
#include "crypto/bn.h"
+#include "crypto/sparse_array.h"
#include "rsa_local.h"
#include "internal/constant_time.h"
#include <openssl/evp.h>
#include <openssl/sha.h>
#include <openssl/hmac.h>
+DEFINE_SPARSE_ARRAY_OF(BN_BLINDING);
+
static int rsa_ossl_public_encrypt(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding);
static int rsa_ossl_private_encrypt(int flen, const unsigned char *from,
return r;
}
-static BN_BLINDING *rsa_get_blinding(RSA *rsa, int *local, BN_CTX *ctx)
+static void free_bn_blinding(ossl_uintmax_t idx, BN_BLINDING *b, void *arg)
{
- BN_BLINDING *ret;
+ BN_BLINDING_free(b);
+}
- if (!CRYPTO_THREAD_read_lock(rsa->lock))
- return NULL;
+void ossl_rsa_free_blinding(RSA *rsa)
+{
+ SPARSE_ARRAY_OF(BN_BLINDING) *blindings = rsa->blindings_sa;
- if (rsa->blinding == NULL) {
- /*
- * 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);
- }
+ ossl_sa_BN_BLINDING_doall_arg(blindings, free_bn_blinding, NULL);
+ ossl_sa_BN_BLINDING_free(blindings);
+}
- ret = rsa->blinding;
- if (ret == NULL)
- goto err;
+void *ossl_rsa_alloc_blinding(void)
+{
+ return ossl_sa_BN_BLINDING_new();
+}
- if (BN_BLINDING_is_current_thread(ret)) {
- /* rsa->blinding is ours! */
+static BN_BLINDING *ossl_rsa_get_thread_bn_blinding(RSA *rsa)
+{
+ SPARSE_ARRAY_OF(BN_BLINDING) *blindings = rsa->blindings_sa;
+ uintptr_t tid = (uintptr_t)CRYPTO_THREAD_get_current_id();
- *local = 1;
- } else {
- /* resort to rsa->mt_blinding instead */
+ return ossl_sa_BN_BLINDING_get(blindings, tid);
+}
- /*
- * instructs rsa_blinding_convert(), rsa_blinding_invert() that the
- * BN_BLINDING is shared, meaning that accesses require locks, and
- * that the blinding factor must be stored outside the BN_BLINDING
- */
- *local = 0;
-
- if (rsa->mt_blinding == NULL) {
- 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;
- }
+static int ossl_rsa_set_thread_bn_blinding(RSA *rsa, BN_BLINDING *b)
+{
+ SPARSE_ARRAY_OF(BN_BLINDING) *blindings = rsa->blindings_sa;
+ uintptr_t tid = (uintptr_t)CRYPTO_THREAD_get_current_id();
- err:
- CRYPTO_THREAD_unlock(rsa->lock);
- return ret;
+ return ossl_sa_BN_BLINDING_set(blindings, tid, b);
}
-static int rsa_blinding_convert(BN_BLINDING *b, BIGNUM *f, BIGNUM *unblind,
- BN_CTX *ctx)
+static BN_BLINDING *rsa_get_blinding(RSA *rsa, BN_CTX *ctx)
{
- if (unblind == NULL) {
- /*
- * Local blinding: store the unblinding factor in BN_BLINDING.
- */
- return BN_BLINDING_convert_ex(f, NULL, b, ctx);
- } else {
- /*
- * Shared blinding: store the unblinding factor outside BN_BLINDING.
- */
- int ret;
+ BN_BLINDING *ret;
- if (!BN_BLINDING_lock(b))
- return 0;
+ if (!CRYPTO_THREAD_read_lock(rsa->lock))
+ return NULL;
- ret = BN_BLINDING_convert_ex(f, unblind, b, ctx);
- BN_BLINDING_unlock(b);
+ ret = ossl_rsa_get_thread_bn_blinding(rsa);
+ CRYPTO_THREAD_unlock(rsa->lock);
- return ret;
+ if (ret == NULL) {
+ ret = RSA_setup_blinding(rsa, ctx);
+ if (!CRYPTO_THREAD_write_lock(rsa->lock)) {
+ BN_BLINDING_free(ret);
+ ret = NULL;
+ } else {
+ if (!ossl_rsa_set_thread_bn_blinding(rsa, ret)) {
+ BN_BLINDING_free(ret);
+ ret = NULL;
+ }
+ }
+ CRYPTO_THREAD_unlock(rsa->lock);
}
+
+ return ret;
}
-static int rsa_blinding_invert(BN_BLINDING *b, BIGNUM *f, BIGNUM *unblind,
- BN_CTX *ctx)
+static int rsa_blinding_convert(BN_BLINDING *b, BIGNUM *f, BN_CTX *ctx)
+{
+ /*
+ * Local blinding: store the unblinding factor in BN_BLINDING.
+ */
+ return BN_BLINDING_convert_ex(f, NULL, b, ctx);
+}
+
+static int rsa_blinding_invert(BN_BLINDING *b, BIGNUM *f, BN_CTX *ctx)
{
/*
* For local blinding, unblind is set to NULL, and BN_BLINDING_invert_ex
* to access the blinding without a lock.
*/
BN_set_flags(f, BN_FLG_CONSTTIME);
- return BN_BLINDING_invert_ex(f, unblind, b, ctx);
+ return BN_BLINDING_invert_ex(f, NULL, b, ctx);
}
/* signing */
int i, num = 0, r = -1;
unsigned char *buf = NULL;
BN_CTX *ctx = NULL;
- int local_blinding = 0;
- /*
- * Used only if the blinding structure is shared. A non-NULL unblind
- * instructs rsa_blinding_convert() and rsa_blinding_invert() to store
- * the unblinding factor outside the blinding structure.
- */
- BIGNUM *unblind = NULL;
BN_BLINDING *blinding = NULL;
if ((ctx = BN_CTX_new_ex(rsa->libctx)) == NULL)
goto err;
if (!(rsa->flags & RSA_FLAG_NO_BLINDING)) {
- blinding = rsa_get_blinding(rsa, &local_blinding, ctx);
+ blinding = rsa_get_blinding(rsa, ctx);
if (blinding == NULL) {
ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR);
goto err;
}
- }
- if (blinding != NULL) {
- if (!local_blinding && ((unblind = BN_CTX_get(ctx)) == NULL)) {
- ERR_raise(ERR_LIB_RSA, ERR_R_BN_LIB);
- goto err;
- }
- if (!rsa_blinding_convert(blinding, f, unblind, ctx))
+ if (!rsa_blinding_convert(blinding, f, ctx))
goto err;
}
}
if (blinding)
- if (!rsa_blinding_invert(blinding, ret, unblind, ctx))
+ if (!rsa_blinding_invert(blinding, ret, ctx))
goto err;
if (padding == RSA_X931_PADDING) {
unsigned char *buf = NULL;
unsigned char kdk[SHA256_DIGEST_LENGTH] = {0};
BN_CTX *ctx = NULL;
- int local_blinding = 0;
- /*
- * Used only if the blinding structure is shared. A non-NULL unblind
- * instructs rsa_blinding_convert() and rsa_blinding_invert() to store
- * the unblinding factor outside the blinding structure.
- */
- BIGNUM *unblind = NULL;
BN_BLINDING *blinding = NULL;
/*
goto err;
if (!(rsa->flags & RSA_FLAG_NO_BLINDING)) {
- blinding = rsa_get_blinding(rsa, &local_blinding, ctx);
+ blinding = rsa_get_blinding(rsa, ctx);
if (blinding == NULL) {
ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR);
goto err;
}
- }
- if (blinding != NULL) {
- if (!local_blinding && ((unblind = BN_CTX_get(ctx)) == NULL)) {
- ERR_raise(ERR_LIB_RSA, ERR_R_BN_LIB);
- goto err;
- }
- if (!rsa_blinding_convert(blinding, f, unblind, ctx))
+ if (!rsa_blinding_convert(blinding, f, ctx))
goto err;
}
}
if (blinding)
- if (!rsa_blinding_invert(blinding, ret, unblind, ctx))
+ if (!rsa_blinding_invert(blinding, ret, ctx))
goto err;
/*