1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 1998-2023 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci#include <openssl/opensslconf.h> 11e1051a39Sopenharmony_ci#include "internal/cryptlib.h" 12e1051a39Sopenharmony_ci#include "bn_local.h" 13e1051a39Sopenharmony_ci 14e1051a39Sopenharmony_ci#define BN_BLINDING_COUNTER 32 15e1051a39Sopenharmony_ci 16e1051a39Sopenharmony_cistruct bn_blinding_st { 17e1051a39Sopenharmony_ci BIGNUM *A; 18e1051a39Sopenharmony_ci BIGNUM *Ai; 19e1051a39Sopenharmony_ci BIGNUM *e; 20e1051a39Sopenharmony_ci BIGNUM *mod; /* just a reference */ 21e1051a39Sopenharmony_ci CRYPTO_THREAD_ID tid; 22e1051a39Sopenharmony_ci int counter; 23e1051a39Sopenharmony_ci unsigned long flags; 24e1051a39Sopenharmony_ci BN_MONT_CTX *m_ctx; 25e1051a39Sopenharmony_ci int (*bn_mod_exp) (BIGNUM *r, const BIGNUM *a, const BIGNUM *p, 26e1051a39Sopenharmony_ci const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); 27e1051a39Sopenharmony_ci CRYPTO_RWLOCK *lock; 28e1051a39Sopenharmony_ci}; 29e1051a39Sopenharmony_ci 30e1051a39Sopenharmony_ciBN_BLINDING *BN_BLINDING_new(const BIGNUM *A, const BIGNUM *Ai, BIGNUM *mod) 31e1051a39Sopenharmony_ci{ 32e1051a39Sopenharmony_ci BN_BLINDING *ret = NULL; 33e1051a39Sopenharmony_ci 34e1051a39Sopenharmony_ci bn_check_top(mod); 35e1051a39Sopenharmony_ci 36e1051a39Sopenharmony_ci if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) { 37e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE); 38e1051a39Sopenharmony_ci return NULL; 39e1051a39Sopenharmony_ci } 40e1051a39Sopenharmony_ci 41e1051a39Sopenharmony_ci ret->lock = CRYPTO_THREAD_lock_new(); 42e1051a39Sopenharmony_ci if (ret->lock == NULL) { 43e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE); 44e1051a39Sopenharmony_ci OPENSSL_free(ret); 45e1051a39Sopenharmony_ci return NULL; 46e1051a39Sopenharmony_ci } 47e1051a39Sopenharmony_ci 48e1051a39Sopenharmony_ci BN_BLINDING_set_current_thread(ret); 49e1051a39Sopenharmony_ci 50e1051a39Sopenharmony_ci if (A != NULL) { 51e1051a39Sopenharmony_ci if ((ret->A = BN_dup(A)) == NULL) 52e1051a39Sopenharmony_ci goto err; 53e1051a39Sopenharmony_ci } 54e1051a39Sopenharmony_ci 55e1051a39Sopenharmony_ci if (Ai != NULL) { 56e1051a39Sopenharmony_ci if ((ret->Ai = BN_dup(Ai)) == NULL) 57e1051a39Sopenharmony_ci goto err; 58e1051a39Sopenharmony_ci } 59e1051a39Sopenharmony_ci 60e1051a39Sopenharmony_ci /* save a copy of mod in the BN_BLINDING structure */ 61e1051a39Sopenharmony_ci if ((ret->mod = BN_dup(mod)) == NULL) 62e1051a39Sopenharmony_ci goto err; 63e1051a39Sopenharmony_ci 64e1051a39Sopenharmony_ci if (BN_get_flags(mod, BN_FLG_CONSTTIME) != 0) 65e1051a39Sopenharmony_ci BN_set_flags(ret->mod, BN_FLG_CONSTTIME); 66e1051a39Sopenharmony_ci 67e1051a39Sopenharmony_ci /* 68e1051a39Sopenharmony_ci * Set the counter to the special value -1 to indicate that this is 69e1051a39Sopenharmony_ci * never-used fresh blinding that does not need updating before first 70e1051a39Sopenharmony_ci * use. 71e1051a39Sopenharmony_ci */ 72e1051a39Sopenharmony_ci ret->counter = -1; 73e1051a39Sopenharmony_ci 74e1051a39Sopenharmony_ci return ret; 75e1051a39Sopenharmony_ci 76e1051a39Sopenharmony_ci err: 77e1051a39Sopenharmony_ci BN_BLINDING_free(ret); 78e1051a39Sopenharmony_ci return NULL; 79e1051a39Sopenharmony_ci} 80e1051a39Sopenharmony_ci 81e1051a39Sopenharmony_civoid BN_BLINDING_free(BN_BLINDING *r) 82e1051a39Sopenharmony_ci{ 83e1051a39Sopenharmony_ci if (r == NULL) 84e1051a39Sopenharmony_ci return; 85e1051a39Sopenharmony_ci BN_free(r->A); 86e1051a39Sopenharmony_ci BN_free(r->Ai); 87e1051a39Sopenharmony_ci BN_free(r->e); 88e1051a39Sopenharmony_ci BN_free(r->mod); 89e1051a39Sopenharmony_ci CRYPTO_THREAD_lock_free(r->lock); 90e1051a39Sopenharmony_ci OPENSSL_free(r); 91e1051a39Sopenharmony_ci} 92e1051a39Sopenharmony_ci 93e1051a39Sopenharmony_ciint BN_BLINDING_update(BN_BLINDING *b, BN_CTX *ctx) 94e1051a39Sopenharmony_ci{ 95e1051a39Sopenharmony_ci int ret = 0; 96e1051a39Sopenharmony_ci 97e1051a39Sopenharmony_ci if ((b->A == NULL) || (b->Ai == NULL)) { 98e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BN, BN_R_NOT_INITIALIZED); 99e1051a39Sopenharmony_ci goto err; 100e1051a39Sopenharmony_ci } 101e1051a39Sopenharmony_ci 102e1051a39Sopenharmony_ci if (b->counter == -1) 103e1051a39Sopenharmony_ci b->counter = 0; 104e1051a39Sopenharmony_ci 105e1051a39Sopenharmony_ci if (++b->counter == BN_BLINDING_COUNTER && b->e != NULL && 106e1051a39Sopenharmony_ci !(b->flags & BN_BLINDING_NO_RECREATE)) { 107e1051a39Sopenharmony_ci /* re-create blinding parameters */ 108e1051a39Sopenharmony_ci if (!BN_BLINDING_create_param(b, NULL, NULL, ctx, NULL, NULL)) 109e1051a39Sopenharmony_ci goto err; 110e1051a39Sopenharmony_ci } else if (!(b->flags & BN_BLINDING_NO_UPDATE)) { 111e1051a39Sopenharmony_ci if (b->m_ctx != NULL) { 112e1051a39Sopenharmony_ci if (!bn_mul_mont_fixed_top(b->Ai, b->Ai, b->Ai, b->m_ctx, ctx) 113e1051a39Sopenharmony_ci || !bn_mul_mont_fixed_top(b->A, b->A, b->A, b->m_ctx, ctx)) 114e1051a39Sopenharmony_ci goto err; 115e1051a39Sopenharmony_ci } else { 116e1051a39Sopenharmony_ci if (!BN_mod_mul(b->Ai, b->Ai, b->Ai, b->mod, ctx) 117e1051a39Sopenharmony_ci || !BN_mod_mul(b->A, b->A, b->A, b->mod, ctx)) 118e1051a39Sopenharmony_ci goto err; 119e1051a39Sopenharmony_ci } 120e1051a39Sopenharmony_ci } 121e1051a39Sopenharmony_ci 122e1051a39Sopenharmony_ci ret = 1; 123e1051a39Sopenharmony_ci err: 124e1051a39Sopenharmony_ci if (b->counter == BN_BLINDING_COUNTER) 125e1051a39Sopenharmony_ci b->counter = 0; 126e1051a39Sopenharmony_ci return ret; 127e1051a39Sopenharmony_ci} 128e1051a39Sopenharmony_ci 129e1051a39Sopenharmony_ciint BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx) 130e1051a39Sopenharmony_ci{ 131e1051a39Sopenharmony_ci return BN_BLINDING_convert_ex(n, NULL, b, ctx); 132e1051a39Sopenharmony_ci} 133e1051a39Sopenharmony_ci 134e1051a39Sopenharmony_ciint BN_BLINDING_convert_ex(BIGNUM *n, BIGNUM *r, BN_BLINDING *b, BN_CTX *ctx) 135e1051a39Sopenharmony_ci{ 136e1051a39Sopenharmony_ci int ret = 1; 137e1051a39Sopenharmony_ci 138e1051a39Sopenharmony_ci bn_check_top(n); 139e1051a39Sopenharmony_ci 140e1051a39Sopenharmony_ci if ((b->A == NULL) || (b->Ai == NULL)) { 141e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BN, BN_R_NOT_INITIALIZED); 142e1051a39Sopenharmony_ci return 0; 143e1051a39Sopenharmony_ci } 144e1051a39Sopenharmony_ci 145e1051a39Sopenharmony_ci if (b->counter == -1) 146e1051a39Sopenharmony_ci /* Fresh blinding, doesn't need updating. */ 147e1051a39Sopenharmony_ci b->counter = 0; 148e1051a39Sopenharmony_ci else if (!BN_BLINDING_update(b, ctx)) 149e1051a39Sopenharmony_ci return 0; 150e1051a39Sopenharmony_ci 151e1051a39Sopenharmony_ci if (r != NULL && (BN_copy(r, b->Ai) == NULL)) 152e1051a39Sopenharmony_ci return 0; 153e1051a39Sopenharmony_ci 154e1051a39Sopenharmony_ci if (b->m_ctx != NULL) 155e1051a39Sopenharmony_ci ret = BN_mod_mul_montgomery(n, n, b->A, b->m_ctx, ctx); 156e1051a39Sopenharmony_ci else 157e1051a39Sopenharmony_ci ret = BN_mod_mul(n, n, b->A, b->mod, ctx); 158e1051a39Sopenharmony_ci 159e1051a39Sopenharmony_ci return ret; 160e1051a39Sopenharmony_ci} 161e1051a39Sopenharmony_ci 162e1051a39Sopenharmony_ciint BN_BLINDING_invert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx) 163e1051a39Sopenharmony_ci{ 164e1051a39Sopenharmony_ci return BN_BLINDING_invert_ex(n, NULL, b, ctx); 165e1051a39Sopenharmony_ci} 166e1051a39Sopenharmony_ci 167e1051a39Sopenharmony_ciint BN_BLINDING_invert_ex(BIGNUM *n, const BIGNUM *r, BN_BLINDING *b, 168e1051a39Sopenharmony_ci BN_CTX *ctx) 169e1051a39Sopenharmony_ci{ 170e1051a39Sopenharmony_ci int ret; 171e1051a39Sopenharmony_ci 172e1051a39Sopenharmony_ci bn_check_top(n); 173e1051a39Sopenharmony_ci 174e1051a39Sopenharmony_ci if (r == NULL && (r = b->Ai) == NULL) { 175e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BN, BN_R_NOT_INITIALIZED); 176e1051a39Sopenharmony_ci return 0; 177e1051a39Sopenharmony_ci } 178e1051a39Sopenharmony_ci 179e1051a39Sopenharmony_ci if (b->m_ctx != NULL) { 180e1051a39Sopenharmony_ci /* ensure that BN_mod_mul_montgomery takes pre-defined path */ 181e1051a39Sopenharmony_ci if (n->dmax >= r->top) { 182e1051a39Sopenharmony_ci size_t i, rtop = r->top, ntop = n->top; 183e1051a39Sopenharmony_ci BN_ULONG mask; 184e1051a39Sopenharmony_ci 185e1051a39Sopenharmony_ci for (i = 0; i < rtop; i++) { 186e1051a39Sopenharmony_ci mask = (BN_ULONG)0 - ((i - ntop) >> (8 * sizeof(i) - 1)); 187e1051a39Sopenharmony_ci n->d[i] &= mask; 188e1051a39Sopenharmony_ci } 189e1051a39Sopenharmony_ci mask = (BN_ULONG)0 - ((rtop - ntop) >> (8 * sizeof(ntop) - 1)); 190e1051a39Sopenharmony_ci /* always true, if (rtop >= ntop) n->top = r->top; */ 191e1051a39Sopenharmony_ci n->top = (int)(rtop & ~mask) | (ntop & mask); 192e1051a39Sopenharmony_ci n->flags |= (BN_FLG_FIXED_TOP & ~mask); 193e1051a39Sopenharmony_ci } 194e1051a39Sopenharmony_ci ret = bn_mul_mont_fixed_top(n, n, r, b->m_ctx, ctx); 195e1051a39Sopenharmony_ci bn_correct_top_consttime(n); 196e1051a39Sopenharmony_ci } else { 197e1051a39Sopenharmony_ci ret = BN_mod_mul(n, n, r, b->mod, ctx); 198e1051a39Sopenharmony_ci } 199e1051a39Sopenharmony_ci 200e1051a39Sopenharmony_ci bn_check_top(n); 201e1051a39Sopenharmony_ci return ret; 202e1051a39Sopenharmony_ci} 203e1051a39Sopenharmony_ci 204e1051a39Sopenharmony_ciint BN_BLINDING_is_current_thread(BN_BLINDING *b) 205e1051a39Sopenharmony_ci{ 206e1051a39Sopenharmony_ci return CRYPTO_THREAD_compare_id(CRYPTO_THREAD_get_current_id(), b->tid); 207e1051a39Sopenharmony_ci} 208e1051a39Sopenharmony_ci 209e1051a39Sopenharmony_civoid BN_BLINDING_set_current_thread(BN_BLINDING *b) 210e1051a39Sopenharmony_ci{ 211e1051a39Sopenharmony_ci b->tid = CRYPTO_THREAD_get_current_id(); 212e1051a39Sopenharmony_ci} 213e1051a39Sopenharmony_ci 214e1051a39Sopenharmony_ciint BN_BLINDING_lock(BN_BLINDING *b) 215e1051a39Sopenharmony_ci{ 216e1051a39Sopenharmony_ci return CRYPTO_THREAD_write_lock(b->lock); 217e1051a39Sopenharmony_ci} 218e1051a39Sopenharmony_ci 219e1051a39Sopenharmony_ciint BN_BLINDING_unlock(BN_BLINDING *b) 220e1051a39Sopenharmony_ci{ 221e1051a39Sopenharmony_ci return CRYPTO_THREAD_unlock(b->lock); 222e1051a39Sopenharmony_ci} 223e1051a39Sopenharmony_ci 224e1051a39Sopenharmony_ciunsigned long BN_BLINDING_get_flags(const BN_BLINDING *b) 225e1051a39Sopenharmony_ci{ 226e1051a39Sopenharmony_ci return b->flags; 227e1051a39Sopenharmony_ci} 228e1051a39Sopenharmony_ci 229e1051a39Sopenharmony_civoid BN_BLINDING_set_flags(BN_BLINDING *b, unsigned long flags) 230e1051a39Sopenharmony_ci{ 231e1051a39Sopenharmony_ci b->flags = flags; 232e1051a39Sopenharmony_ci} 233e1051a39Sopenharmony_ci 234e1051a39Sopenharmony_ciBN_BLINDING *BN_BLINDING_create_param(BN_BLINDING *b, 235e1051a39Sopenharmony_ci const BIGNUM *e, BIGNUM *m, BN_CTX *ctx, 236e1051a39Sopenharmony_ci int (*bn_mod_exp) (BIGNUM *r, 237e1051a39Sopenharmony_ci const BIGNUM *a, 238e1051a39Sopenharmony_ci const BIGNUM *p, 239e1051a39Sopenharmony_ci const BIGNUM *m, 240e1051a39Sopenharmony_ci BN_CTX *ctx, 241e1051a39Sopenharmony_ci BN_MONT_CTX *m_ctx), 242e1051a39Sopenharmony_ci BN_MONT_CTX *m_ctx) 243e1051a39Sopenharmony_ci{ 244e1051a39Sopenharmony_ci int retry_counter = 32; 245e1051a39Sopenharmony_ci BN_BLINDING *ret = NULL; 246e1051a39Sopenharmony_ci 247e1051a39Sopenharmony_ci if (b == NULL) 248e1051a39Sopenharmony_ci ret = BN_BLINDING_new(NULL, NULL, m); 249e1051a39Sopenharmony_ci else 250e1051a39Sopenharmony_ci ret = b; 251e1051a39Sopenharmony_ci 252e1051a39Sopenharmony_ci if (ret == NULL) 253e1051a39Sopenharmony_ci goto err; 254e1051a39Sopenharmony_ci 255e1051a39Sopenharmony_ci if (ret->A == NULL && (ret->A = BN_new()) == NULL) 256e1051a39Sopenharmony_ci goto err; 257e1051a39Sopenharmony_ci if (ret->Ai == NULL && (ret->Ai = BN_new()) == NULL) 258e1051a39Sopenharmony_ci goto err; 259e1051a39Sopenharmony_ci 260e1051a39Sopenharmony_ci if (e != NULL) { 261e1051a39Sopenharmony_ci BN_free(ret->e); 262e1051a39Sopenharmony_ci ret->e = BN_dup(e); 263e1051a39Sopenharmony_ci } 264e1051a39Sopenharmony_ci if (ret->e == NULL) 265e1051a39Sopenharmony_ci goto err; 266e1051a39Sopenharmony_ci 267e1051a39Sopenharmony_ci if (bn_mod_exp != NULL) 268e1051a39Sopenharmony_ci ret->bn_mod_exp = bn_mod_exp; 269e1051a39Sopenharmony_ci if (m_ctx != NULL) 270e1051a39Sopenharmony_ci ret->m_ctx = m_ctx; 271e1051a39Sopenharmony_ci 272e1051a39Sopenharmony_ci do { 273e1051a39Sopenharmony_ci int rv; 274e1051a39Sopenharmony_ci if (!BN_priv_rand_range_ex(ret->A, ret->mod, 0, ctx)) 275e1051a39Sopenharmony_ci goto err; 276e1051a39Sopenharmony_ci if (int_bn_mod_inverse(ret->Ai, ret->A, ret->mod, ctx, &rv)) 277e1051a39Sopenharmony_ci break; 278e1051a39Sopenharmony_ci 279e1051a39Sopenharmony_ci /* 280e1051a39Sopenharmony_ci * this should almost never happen for good RSA keys 281e1051a39Sopenharmony_ci */ 282e1051a39Sopenharmony_ci if (!rv) 283e1051a39Sopenharmony_ci goto err; 284e1051a39Sopenharmony_ci 285e1051a39Sopenharmony_ci if (retry_counter-- == 0) { 286e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BN, BN_R_TOO_MANY_ITERATIONS); 287e1051a39Sopenharmony_ci goto err; 288e1051a39Sopenharmony_ci } 289e1051a39Sopenharmony_ci } while (1); 290e1051a39Sopenharmony_ci 291e1051a39Sopenharmony_ci if (ret->bn_mod_exp != NULL && ret->m_ctx != NULL) { 292e1051a39Sopenharmony_ci if (!ret->bn_mod_exp(ret->A, ret->A, ret->e, ret->mod, ctx, ret->m_ctx)) 293e1051a39Sopenharmony_ci goto err; 294e1051a39Sopenharmony_ci } else { 295e1051a39Sopenharmony_ci if (!BN_mod_exp(ret->A, ret->A, ret->e, ret->mod, ctx)) 296e1051a39Sopenharmony_ci goto err; 297e1051a39Sopenharmony_ci } 298e1051a39Sopenharmony_ci 299e1051a39Sopenharmony_ci if (ret->m_ctx != NULL) { 300e1051a39Sopenharmony_ci if (!bn_to_mont_fixed_top(ret->Ai, ret->Ai, ret->m_ctx, ctx) 301e1051a39Sopenharmony_ci || !bn_to_mont_fixed_top(ret->A, ret->A, ret->m_ctx, ctx)) 302e1051a39Sopenharmony_ci goto err; 303e1051a39Sopenharmony_ci } 304e1051a39Sopenharmony_ci 305e1051a39Sopenharmony_ci return ret; 306e1051a39Sopenharmony_ci err: 307e1051a39Sopenharmony_ci if (b == NULL) { 308e1051a39Sopenharmony_ci BN_BLINDING_free(ret); 309e1051a39Sopenharmony_ci ret = NULL; 310e1051a39Sopenharmony_ci } 311e1051a39Sopenharmony_ci 312e1051a39Sopenharmony_ci return ret; 313e1051a39Sopenharmony_ci} 314