1 /* $OpenBSD: rsa_blinding.c,v 1.3 2023/08/09 12:09:06 tb Exp $ */ 2 /* ==================================================================== 3 * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in 14 * the documentation and/or other materials provided with the 15 * distribution. 16 * 17 * 3. All advertising materials mentioning features or use of this 18 * software must display the following acknowledgment: 19 * "This product includes software developed by the OpenSSL Project 20 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 21 * 22 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 23 * endorse or promote products derived from this software without 24 * prior written permission. For written permission, please contact 25 * openssl-core@openssl.org. 26 * 27 * 5. Products derived from this software may not be called "OpenSSL" 28 * nor may "OpenSSL" appear in their names without prior written 29 * permission of the OpenSSL Project. 30 * 31 * 6. Redistributions of any form whatsoever must retain the following 32 * acknowledgment: 33 * "This product includes software developed by the OpenSSL Project 34 * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 35 * 36 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 37 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 38 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 39 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 40 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 41 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 42 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 43 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 44 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 45 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 46 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 47 * OF THE POSSIBILITY OF SUCH DAMAGE. 48 * ==================================================================== 49 * 50 * This product includes cryptographic software written by Eric Young 51 * (eay@cryptsoft.com). This product includes software written by Tim 52 * Hudson (tjh@cryptsoft.com). 53 * 54 */ 55 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 56 * All rights reserved. 57 * 58 * This package is an SSL implementation written 59 * by Eric Young (eay@cryptsoft.com). 60 * The implementation was written so as to conform with Netscapes SSL. 61 * 62 * This library is free for commercial and non-commercial use as long as 63 * the following conditions are aheared to. The following conditions 64 * apply to all code found in this distribution, be it the RC4, RSA, 65 * lhash, DES, etc., code; not just the SSL code. The SSL documentation 66 * included with this distribution is covered by the same copyright terms 67 * except that the holder is Tim Hudson (tjh@cryptsoft.com). 68 * 69 * Copyright remains Eric Young's, and as such any Copyright notices in 70 * the code are not to be removed. 71 * If this package is used in a product, Eric Young should be given attribution 72 * as the author of the parts of the library used. 73 * This can be in the form of a textual message at program startup or 74 * in documentation (online or textual) provided with the package. 75 * 76 * Redistribution and use in source and binary forms, with or without 77 * modification, are permitted provided that the following conditions 78 * are met: 79 * 1. Redistributions of source code must retain the copyright 80 * notice, this list of conditions and the following disclaimer. 81 * 2. Redistributions in binary form must reproduce the above copyright 82 * notice, this list of conditions and the following disclaimer in the 83 * documentation and/or other materials provided with the distribution. 84 * 3. All advertising materials mentioning features or use of this software 85 * must display the following acknowledgement: 86 * "This product includes cryptographic software written by 87 * Eric Young (eay@cryptsoft.com)" 88 * The word 'cryptographic' can be left out if the rouines from the library 89 * being used are not cryptographic related :-). 90 * 4. If you include any Windows specific code (or a derivative thereof) from 91 * the apps directory (application code) you must include an acknowledgement: 92 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 93 * 94 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 95 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 96 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 97 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 98 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 99 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 100 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 101 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 102 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 103 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 104 * SUCH DAMAGE. 105 * 106 * The licence and distribution terms for any publically available version or 107 * derivative of this code cannot be changed. i.e. this code cannot simply be 108 * copied and put under another distribution licence 109 * [including the GNU Public Licence.] 110 */ 111 112 #include <pthread.h> 113 #include <stdio.h> 114 115 #include <openssl/opensslconf.h> 116 117 #include <openssl/err.h> 118 #include <openssl/rsa.h> 119 120 #include "bn_local.h" 121 #include "rsa_local.h" 122 123 #define BN_BLINDING_COUNTER 32 124 125 struct bn_blinding_st { 126 BIGNUM *A; 127 BIGNUM *Ai; 128 BIGNUM *e; 129 BIGNUM *mod; 130 pthread_t tid; 131 int counter; 132 BN_MONT_CTX *m_ctx; 133 int (*bn_mod_exp)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, 134 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); 135 }; 136 137 BN_BLINDING * 138 BN_BLINDING_new(const BIGNUM *e, const BIGNUM *mod, BN_CTX *ctx, 139 int (*bn_mod_exp)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, 140 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx), BN_MONT_CTX *m_ctx) 141 { 142 BN_BLINDING *ret = NULL; 143 144 if ((ret = calloc(1, sizeof(BN_BLINDING))) == NULL) { 145 BNerror(ERR_R_MALLOC_FAILURE); 146 goto err; 147 } 148 if ((ret->A = BN_new()) == NULL) 149 goto err; 150 if ((ret->Ai = BN_new()) == NULL) 151 goto err; 152 if ((ret->e = BN_dup(e)) == NULL) 153 goto err; 154 if ((ret->mod = BN_dup(mod)) == NULL) 155 goto err; 156 if (BN_get_flags(mod, BN_FLG_CONSTTIME) != 0) 157 BN_set_flags(ret->mod, BN_FLG_CONSTTIME); 158 159 /* Update on first use. */ 160 ret->counter = BN_BLINDING_COUNTER - 1; 161 ret->tid = pthread_self(); 162 163 if (bn_mod_exp != NULL) 164 ret->bn_mod_exp = bn_mod_exp; 165 if (m_ctx != NULL) 166 ret->m_ctx = m_ctx; 167 168 return ret; 169 170 err: 171 BN_BLINDING_free(ret); 172 173 return NULL; 174 } 175 176 void 177 BN_BLINDING_free(BN_BLINDING *r) 178 { 179 if (r == NULL) 180 return; 181 182 BN_free(r->A); 183 BN_free(r->Ai); 184 BN_free(r->e); 185 BN_free(r->mod); 186 free(r); 187 } 188 189 static int 190 BN_BLINDING_setup(BN_BLINDING *b, BN_CTX *ctx) 191 { 192 if (!bn_rand_interval(b->A, 1, b->mod)) 193 return 0; 194 if (BN_mod_inverse_ct(b->Ai, b->A, b->mod, ctx) == NULL) 195 return 0; 196 197 if (b->bn_mod_exp != NULL && b->m_ctx != NULL) { 198 if (!b->bn_mod_exp(b->A, b->A, b->e, b->mod, ctx, b->m_ctx)) 199 return 0; 200 } else { 201 if (!BN_mod_exp_ct(b->A, b->A, b->e, b->mod, ctx)) 202 return 0; 203 } 204 205 return 1; 206 } 207 208 static int 209 BN_BLINDING_update(BN_BLINDING *b, BN_CTX *ctx) 210 { 211 int ret = 0; 212 213 if (++b->counter >= BN_BLINDING_COUNTER) { 214 if (!BN_BLINDING_setup(b, ctx)) 215 goto err; 216 b->counter = 0; 217 } else { 218 if (!BN_mod_sqr(b->A, b->A, b->mod, ctx)) 219 goto err; 220 if (!BN_mod_sqr(b->Ai, b->Ai, b->mod, ctx)) 221 goto err; 222 } 223 224 ret = 1; 225 226 err: 227 return ret; 228 } 229 230 int 231 BN_BLINDING_convert(BIGNUM *n, BIGNUM *inv, BN_BLINDING *b, BN_CTX *ctx) 232 { 233 int ret = 0; 234 235 if (!BN_BLINDING_update(b, ctx)) 236 goto err; 237 238 if (inv != NULL) { 239 if (!bn_copy(inv, b->Ai)) 240 goto err; 241 } 242 243 ret = BN_mod_mul(n, n, b->A, b->mod, ctx); 244 245 err: 246 return ret; 247 } 248 249 int 250 BN_BLINDING_invert(BIGNUM *n, const BIGNUM *inv, BN_BLINDING *b, BN_CTX *ctx) 251 { 252 if (inv == NULL) 253 inv = b->Ai; 254 255 return BN_mod_mul(n, n, inv, b->mod, ctx); 256 } 257 258 int 259 BN_BLINDING_is_local(BN_BLINDING *b) 260 { 261 return pthread_equal(pthread_self(), b->tid) != 0; 262 } 263 264 static BIGNUM * 265 rsa_get_public_exp(const BIGNUM *d, const BIGNUM *p, const BIGNUM *q, 266 BN_CTX *ctx) 267 { 268 BIGNUM *ret = NULL, *r0, *r1, *r2; 269 270 if (d == NULL || p == NULL || q == NULL) 271 return NULL; 272 273 BN_CTX_start(ctx); 274 if ((r0 = BN_CTX_get(ctx)) == NULL) 275 goto err; 276 if ((r1 = BN_CTX_get(ctx)) == NULL) 277 goto err; 278 if ((r2 = BN_CTX_get(ctx)) == NULL) 279 goto err; 280 281 if (!BN_sub(r1, p, BN_value_one())) 282 goto err; 283 if (!BN_sub(r2, q, BN_value_one())) 284 goto err; 285 if (!BN_mul(r0, r1, r2, ctx)) 286 goto err; 287 288 ret = BN_mod_inverse_ct(NULL, d, r0, ctx); 289 err: 290 BN_CTX_end(ctx); 291 return ret; 292 } 293 294 BN_BLINDING * 295 RSA_setup_blinding(RSA *rsa, BN_CTX *in_ctx) 296 { 297 BIGNUM *e = NULL; 298 BIGNUM n; 299 BN_CTX *ctx = NULL; 300 BN_BLINDING *ret = NULL; 301 302 if ((ctx = in_ctx) == NULL) 303 ctx = BN_CTX_new(); 304 if (ctx == NULL) 305 goto err; 306 307 BN_CTX_start(ctx); 308 309 if ((e = rsa->e) == NULL) 310 e = rsa_get_public_exp(rsa->d, rsa->p, rsa->q, ctx); 311 if (e == NULL) { 312 RSAerror(RSA_R_NO_PUBLIC_EXPONENT); 313 goto err; 314 } 315 316 BN_init(&n); 317 BN_with_flags(&n, rsa->n, BN_FLG_CONSTTIME); 318 319 if ((ret = BN_BLINDING_new(e, &n, ctx, rsa->meth->bn_mod_exp, 320 rsa->_method_mod_n)) == NULL) { 321 RSAerror(ERR_R_BN_LIB); 322 goto err; 323 } 324 325 err: 326 BN_CTX_end(ctx); 327 if (ctx != in_ctx) 328 BN_CTX_free(ctx); 329 if (e != rsa->e) 330 BN_free(e); 331 332 return ret; 333 } 334 335 void 336 RSA_blinding_off(RSA *rsa) 337 { 338 BN_BLINDING_free(rsa->blinding); 339 rsa->blinding = NULL; 340 rsa->flags |= RSA_FLAG_NO_BLINDING; 341 } 342 LCRYPTO_ALIAS(RSA_blinding_off); 343 344 int 345 RSA_blinding_on(RSA *rsa, BN_CTX *ctx) 346 { 347 int ret = 0; 348 349 if (rsa->blinding != NULL) 350 RSA_blinding_off(rsa); 351 352 rsa->blinding = RSA_setup_blinding(rsa, ctx); 353 if (rsa->blinding == NULL) 354 goto err; 355 356 rsa->flags &= ~RSA_FLAG_NO_BLINDING; 357 ret = 1; 358 err: 359 return (ret); 360 } 361 LCRYPTO_ALIAS(RSA_blinding_on); 362