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