1/* 2 * Copyright 1995-2016 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/rsa.h> 11 12#include <string.h> 13 14#include <openssl/bn.h> 15#include <openssl/err.h> 16#include <openssl/mem.h> 17 18#include "../../internal.h" 19#include "internal.h" 20 21 22#define BN_BLINDING_COUNTER 32 23 24struct bn_blinding_st { 25 BIGNUM *A; // The base blinding factor, Montgomery-encoded. 26 BIGNUM *Ai; // The inverse of the blinding factor, Montgomery-encoded. 27 unsigned counter; 28}; 29 30static int bn_blinding_create_param(BN_BLINDING *b, const BIGNUM *e, 31 const BN_MONT_CTX *mont, BN_CTX *ctx); 32 33BN_BLINDING *BN_BLINDING_new(void) { 34 BN_BLINDING *ret = 35 reinterpret_cast<BN_BLINDING *>(OPENSSL_zalloc(sizeof(BN_BLINDING))); 36 if (ret == NULL) { 37 return NULL; 38 } 39 40 ret->A = BN_new(); 41 if (ret->A == NULL) { 42 goto err; 43 } 44 45 ret->Ai = BN_new(); 46 if (ret->Ai == NULL) { 47 goto err; 48 } 49 50 // The blinding values need to be created before this blinding can be used. 51 ret->counter = BN_BLINDING_COUNTER - 1; 52 53 return ret; 54 55err: 56 BN_BLINDING_free(ret); 57 return NULL; 58} 59 60void BN_BLINDING_free(BN_BLINDING *r) { 61 if (r == nullptr) { 62 return; 63 } 64 BN_free(r->A); 65 BN_free(r->Ai); 66 OPENSSL_free(r); 67} 68 69void BN_BLINDING_invalidate(BN_BLINDING *b) { 70 b->counter = BN_BLINDING_COUNTER - 1; 71} 72 73static int bn_blinding_update(BN_BLINDING *b, const BIGNUM *e, 74 const BN_MONT_CTX *mont, BN_CTX *ctx) { 75 if (++b->counter == BN_BLINDING_COUNTER) { 76 // re-create blinding parameters 77 if (!bn_blinding_create_param(b, e, mont, ctx)) { 78 goto err; 79 } 80 b->counter = 0; 81 } else { 82 if (!BN_mod_mul_montgomery(b->A, b->A, b->A, mont, ctx) || 83 !BN_mod_mul_montgomery(b->Ai, b->Ai, b->Ai, mont, ctx)) { 84 goto err; 85 } 86 } 87 88 return 1; 89 90err: 91 // |A| and |Ai| may be in an inconsistent state so they both need to be 92 // replaced the next time this blinding is used. Note that this is only 93 // sufficient because support for |BN_BLINDING_NO_UPDATE| and 94 // |BN_BLINDING_NO_RECREATE| was previously dropped. 95 b->counter = BN_BLINDING_COUNTER - 1; 96 97 return 0; 98} 99 100int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, const BIGNUM *e, 101 const BN_MONT_CTX *mont, BN_CTX *ctx) { 102 // |n| is not Montgomery-encoded and |b->A| is. |BN_mod_mul_montgomery| 103 // cancels one Montgomery factor, so the resulting value of |n| is unencoded. 104 if (!bn_blinding_update(b, e, mont, ctx) || 105 !BN_mod_mul_montgomery(n, n, b->A, mont, ctx)) { 106 return 0; 107 } 108 109 return 1; 110} 111 112int BN_BLINDING_invert(BIGNUM *n, const BN_BLINDING *b, BN_MONT_CTX *mont, 113 BN_CTX *ctx) { 114 // |n| is not Montgomery-encoded and |b->A| is. |BN_mod_mul_montgomery| 115 // cancels one Montgomery factor, so the resulting value of |n| is unencoded. 116 return BN_mod_mul_montgomery(n, n, b->Ai, mont, ctx); 117} 118 119static int bn_blinding_create_param(BN_BLINDING *b, const BIGNUM *e, 120 const BN_MONT_CTX *mont, BN_CTX *ctx) { 121 int no_inverse; 122 if (!BN_rand_range_ex(b->A, 1, &mont->N) || 123 // Compute |b->A|^-1 in Montgomery form. Note |BN_from_montgomery| + 124 // |BN_mod_inverse_blinded| is equivalent to, but more efficient than, 125 // |BN_mod_inverse_blinded| + |BN_to_montgomery|. 126 // 127 // We do not retry if |b->A| has no inverse. Finding a non-invertible 128 // value of |b->A| is equivalent to factoring |mont->N|. There is 129 // negligible probability of stumbling on one at random. 130 !BN_from_montgomery(b->Ai, b->A, mont, ctx) || 131 !BN_mod_inverse_blinded(b->Ai, &no_inverse, b->Ai, mont, ctx) || 132 // TODO(davidben): |BN_mod_exp_mont| internally computes the result in 133 // Montgomery form. Save a pair of Montgomery reductions and a 134 // multiplication by returning that value directly. 135 !BN_mod_exp_mont(b->A, b->A, e, &mont->N, ctx, mont) || 136 !BN_to_montgomery(b->A, b->A, mont, ctx)) { 137 OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); 138 return 0; 139 } 140 141 return 1; 142} 143