/* rsa_blinding_get returns a BN_BLINDING to use with |rsa|. It does this by * allocating one of the cached BN_BLINDING objects in |rsa->blindings|. If * none are free, the cache will be extended by a extra element and the new * BN_BLINDING is returned. * * On success, the index of the assigned BN_BLINDING is written to * |*index_used| and must be passed to |rsa_blinding_release| when finished. */ static BN_BLINDING *rsa_blinding_get(RSA *rsa, unsigned *index_used, BN_CTX *ctx) { BN_BLINDING *ret = NULL; BN_BLINDING **new_blindings; uint8_t *new_blindings_inuse; char overflow = 0; CRYPTO_MUTEX_lock_write(&rsa->lock); unsigned i; for (i = 0; i < rsa->num_blindings; i++) { if (rsa->blindings_inuse[i] == 0) { rsa->blindings_inuse[i] = 1; ret = rsa->blindings[i]; *index_used = i; break; } } if (ret != NULL) { CRYPTO_MUTEX_unlock(&rsa->lock); return ret; } overflow = rsa->num_blindings >= MAX_BLINDINGS_PER_RSA; /* We didn't find a free BN_BLINDING to use so increase the length of * the arrays by one and use the newly created element. */ CRYPTO_MUTEX_unlock(&rsa->lock); ret = rsa_setup_blinding(rsa, ctx); if (ret == NULL) { return NULL; } if (overflow) { /* We cannot add any more cached BN_BLINDINGs so we use |ret| * and mark it for destruction in |rsa_blinding_release|. */ *index_used = MAX_BLINDINGS_PER_RSA; return ret; } CRYPTO_MUTEX_lock_write(&rsa->lock); new_blindings = OPENSSL_malloc(sizeof(BN_BLINDING *) * (rsa->num_blindings + 1)); if (new_blindings == NULL) { goto err1; } memcpy(new_blindings, rsa->blindings, sizeof(BN_BLINDING *) * rsa->num_blindings); new_blindings[rsa->num_blindings] = ret; new_blindings_inuse = OPENSSL_malloc(rsa->num_blindings + 1); if (new_blindings_inuse == NULL) { goto err2; } memcpy(new_blindings_inuse, rsa->blindings_inuse, rsa->num_blindings); new_blindings_inuse[rsa->num_blindings] = 1; *index_used = rsa->num_blindings; OPENSSL_free(rsa->blindings); rsa->blindings = new_blindings; OPENSSL_free(rsa->blindings_inuse); rsa->blindings_inuse = new_blindings_inuse; rsa->num_blindings++; CRYPTO_MUTEX_unlock(&rsa->lock); return ret; err2: OPENSSL_free(new_blindings); err1: CRYPTO_MUTEX_unlock(&rsa->lock); BN_BLINDING_free(ret); return NULL; }
/* rsa_blinding_get returns a BN_BLINDING to use with |rsa|. It does this by * allocating one of the cached BN_BLINDING objects in |rsa->blindings|. If * none are free, the cache will be extended by a extra element and the new * BN_BLINDING is returned. * * On success, the index of the assigned BN_BLINDING is written to * |*index_used| and must be passed to |rsa_blinding_release| when finished. */ static BN_BLINDING *rsa_blinding_get(RSA *rsa, unsigned *index_used, BN_CTX *ctx) { BN_BLINDING *ret = NULL; BN_BLINDING **new_blindings; uint8_t *new_blindings_inuse; char overflow = 0; CRYPTO_w_lock(CRYPTO_LOCK_RSA_BLINDING); if (rsa->num_blindings > 0) { unsigned i, starting_index; CRYPTO_THREADID threadid; /* We start searching the array at a value based on the * threadid in order to try avoid bouncing the BN_BLINDING * values around different threads. It's harmless if * threadid.val is always set to zero. */ CRYPTO_THREADID_current(&threadid); starting_index = threadid.val % rsa->num_blindings; for (i = starting_index;;) { if (rsa->blindings_inuse[i] == 0) { rsa->blindings_inuse[i] = 1; ret = rsa->blindings[i]; *index_used = i; break; } i++; if (i == rsa->num_blindings) { i = 0; } if (i == starting_index) { break; } } } if (ret != NULL) { CRYPTO_w_unlock(CRYPTO_LOCK_RSA_BLINDING); return ret; } overflow = rsa->num_blindings >= MAX_BLINDINGS_PER_RSA; /* We didn't find a free BN_BLINDING to use so increase the length of * the arrays by one and use the newly created element. */ CRYPTO_w_unlock(CRYPTO_LOCK_RSA_BLINDING); ret = rsa_setup_blinding(rsa, ctx); if (ret == NULL) { return NULL; } if (overflow) { /* We cannot add any more cached BN_BLINDINGs so we use |ret| * and mark it for destruction in |rsa_blinding_release|. */ *index_used = MAX_BLINDINGS_PER_RSA; return ret; } CRYPTO_w_lock(CRYPTO_LOCK_RSA_BLINDING); new_blindings = OPENSSL_malloc(sizeof(BN_BLINDING *) * (rsa->num_blindings + 1)); if (new_blindings == NULL) { goto err1; } memcpy(new_blindings, rsa->blindings, sizeof(BN_BLINDING *) * rsa->num_blindings); new_blindings[rsa->num_blindings] = ret; new_blindings_inuse = OPENSSL_malloc(rsa->num_blindings + 1); if (new_blindings_inuse == NULL) { goto err2; } memcpy(new_blindings_inuse, rsa->blindings_inuse, rsa->num_blindings); new_blindings_inuse[rsa->num_blindings] = 1; *index_used = rsa->num_blindings; if (rsa->blindings != NULL) { OPENSSL_free(rsa->blindings); } rsa->blindings = new_blindings; if (rsa->blindings_inuse != NULL) { OPENSSL_free(rsa->blindings_inuse); } rsa->blindings_inuse = new_blindings_inuse; rsa->num_blindings++; CRYPTO_w_unlock(CRYPTO_LOCK_RSA_BLINDING); return ret; err2: OPENSSL_free(new_blindings); err1: CRYPTO_w_unlock(CRYPTO_LOCK_RSA_BLINDING); BN_BLINDING_free(ret); return NULL; }