bn_blind.c 7.0 KB
Newer Older
R
Rich Salz 已提交
1 2
/*
 * Copyright 1998-2016 The OpenSSL Project Authors. All Rights Reserved.
3
 *
R
Rich Salz 已提交
4 5 6 7
 * Licensed under the OpenSSL license (the "License").  You may not use
 * this file except in compliance with the License.  You can obtain a copy
 * in the file LICENSE in the source distribution or at
 * https://www.openssl.org/source/license.html
8 9
 */

10
#include <openssl/opensslconf.h>
11
#include "internal/cryptlib.h"
12 13
#include "bn_lcl.h"

14
#define BN_BLINDING_COUNTER     32
15

16 17 18 19 20
struct bn_blinding_st {
    BIGNUM *A;
    BIGNUM *Ai;
    BIGNUM *e;
    BIGNUM *mod;                /* just a reference */
21
    CRYPTO_THREAD_ID tid;
22 23 24 25 26
    int counter;
    unsigned long flags;
    BN_MONT_CTX *m_ctx;
    int (*bn_mod_exp) (BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
                       const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
27
    CRYPTO_RWLOCK *lock;
28
};
29 30

BN_BLINDING *BN_BLINDING_new(const BIGNUM *A, const BIGNUM *Ai, BIGNUM *mod)
31 32 33 34 35
{
    BN_BLINDING *ret = NULL;

    bn_check_top(mod);

R
Rich Salz 已提交
36
    if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) {
37
        BNerr(BN_F_BN_BLINDING_NEW, ERR_R_MALLOC_FAILURE);
38
        return NULL;
39
    }
40 41 42 43 44 45 46 47 48 49

    ret->lock = CRYPTO_THREAD_lock_new();
    if (ret->lock == NULL) {
        BNerr(BN_F_BN_BLINDING_NEW, ERR_R_MALLOC_FAILURE);
        OPENSSL_free(ret);
        return NULL;
    }

    BN_BLINDING_set_current_thread(ret);

50 51 52 53
    if (A != NULL) {
        if ((ret->A = BN_dup(A)) == NULL)
            goto err;
    }
54

55 56 57 58 59 60 61 62
    if (Ai != NULL) {
        if ((ret->Ai = BN_dup(Ai)) == NULL)
            goto err;
    }

    /* save a copy of mod in the BN_BLINDING structure */
    if ((ret->mod = BN_dup(mod)) == NULL)
        goto err;
63

64 65 66 67 68 69 70 71 72
    if (BN_get_flags(mod, BN_FLG_CONSTTIME) != 0)
        BN_set_flags(ret->mod, BN_FLG_CONSTTIME);

    /*
     * Set the counter to the special value -1 to indicate that this is
     * never-used fresh blinding that does not need updating before first
     * use.
     */
    ret->counter = -1;
73 74 75

    return ret;

76
 err:
R
Rich Salz 已提交
77
    BN_BLINDING_free(ret);
78
    return NULL;
79
}
80

U
Ulf Möller 已提交
81
void BN_BLINDING_free(BN_BLINDING *r)
82 83 84 85
{
    if (r == NULL)
        return;

R
Rich Salz 已提交
86 87 88 89
    BN_free(r->A);
    BN_free(r->Ai);
    BN_free(r->e);
    BN_free(r->mod);
90
    CRYPTO_THREAD_lock_free(r->lock);
91 92
    OPENSSL_free(r);
}
93

U
Ulf Möller 已提交
94
int BN_BLINDING_update(BN_BLINDING *b, BN_CTX *ctx)
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
{
    int ret = 0;

    if ((b->A == NULL) || (b->Ai == NULL)) {
        BNerr(BN_F_BN_BLINDING_UPDATE, BN_R_NOT_INITIALIZED);
        goto err;
    }

    if (b->counter == -1)
        b->counter = 0;

    if (++b->counter == BN_BLINDING_COUNTER && b->e != NULL &&
        !(b->flags & BN_BLINDING_NO_RECREATE)) {
        /* re-create blinding parameters */
        if (!BN_BLINDING_create_param(b, NULL, NULL, ctx, NULL, NULL))
            goto err;
    } else if (!(b->flags & BN_BLINDING_NO_UPDATE)) {
        if (!BN_mod_mul(b->A, b->A, b->A, b->mod, ctx))
            goto err;
        if (!BN_mod_mul(b->Ai, b->Ai, b->Ai, b->mod, ctx))
            goto err;
    }

    ret = 1;
 err:
    if (b->counter == BN_BLINDING_COUNTER)
        b->counter = 0;
    return (ret);
}
124

U
Ulf Möller 已提交
125
int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx)
126 127 128
{
    return BN_BLINDING_convert_ex(n, NULL, b, ctx);
}
129 130

int BN_BLINDING_convert_ex(BIGNUM *n, BIGNUM *r, BN_BLINDING *b, BN_CTX *ctx)
131 132
{
    int ret = 1;
B
Bodo Möller 已提交
133

134
    bn_check_top(n);
135

136 137 138 139
    if ((b->A == NULL) || (b->Ai == NULL)) {
        BNerr(BN_F_BN_BLINDING_CONVERT_EX, BN_R_NOT_INITIALIZED);
        return (0);
    }
140

141 142 143 144 145
    if (b->counter == -1)
        /* Fresh blinding, doesn't need updating. */
        b->counter = 0;
    else if (!BN_BLINDING_update(b, ctx))
        return (0);
B
Bodo Möller 已提交
146

147 148 149 150
    if (r != NULL) {
        if (!BN_copy(r, b->Ai))
            ret = 0;
    }
151

152 153 154 155 156
    if (!BN_mod_mul(n, n, b->A, b->mod, ctx))
        ret = 0;

    return ret;
}
157

U
Ulf Möller 已提交
158
int BN_BLINDING_invert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx)
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
{
    return BN_BLINDING_invert_ex(n, NULL, b, ctx);
}

int BN_BLINDING_invert_ex(BIGNUM *n, const BIGNUM *r, BN_BLINDING *b,
                          BN_CTX *ctx)
{
    int ret;

    bn_check_top(n);

    if (r != NULL)
        ret = BN_mod_mul(n, n, r, b->mod, ctx);
    else {
        if (b->Ai == NULL) {
            BNerr(BN_F_BN_BLINDING_INVERT_EX, BN_R_NOT_INITIALIZED);
            return (0);
        }
        ret = BN_mod_mul(n, n, b->Ai, b->mod, ctx);
    }

    bn_check_top(n);
    return (ret);
}
183

184 185 186 187 188 189
int BN_BLINDING_is_current_thread(BN_BLINDING *b)
{
    return CRYPTO_THREAD_compare_id(CRYPTO_THREAD_get_current_id(), b->tid);
}

void BN_BLINDING_set_current_thread(BN_BLINDING *b)
190
{
191
    b->tid = CRYPTO_THREAD_get_current_id();
192
}
193

194
int BN_BLINDING_lock(BN_BLINDING *b)
195
{
196
    return CRYPTO_THREAD_write_lock(b->lock);
197
}
198

199
int BN_BLINDING_unlock(BN_BLINDING *b)
200
{
201
    return CRYPTO_THREAD_unlock(b->lock);
202
}
203

204
unsigned long BN_BLINDING_get_flags(const BN_BLINDING *b)
205 206 207
{
    return b->flags;
}
208 209

void BN_BLINDING_set_flags(BN_BLINDING *b, unsigned long flags)
210 211 212
{
    b->flags = flags;
}
213 214

BN_BLINDING *BN_BLINDING_create_param(BN_BLINDING *b,
215 216 217 218 219 220 221 222
                                      const BIGNUM *e, BIGNUM *m, BN_CTX *ctx,
                                      int (*bn_mod_exp) (BIGNUM *r,
                                                         const BIGNUM *a,
                                                         const BIGNUM *p,
                                                         const BIGNUM *m,
                                                         BN_CTX *ctx,
                                                         BN_MONT_CTX *m_ctx),
                                      BN_MONT_CTX *m_ctx)
223
{
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240
    int retry_counter = 32;
    BN_BLINDING *ret = NULL;

    if (b == NULL)
        ret = BN_BLINDING_new(NULL, NULL, m);
    else
        ret = b;

    if (ret == NULL)
        goto err;

    if (ret->A == NULL && (ret->A = BN_new()) == NULL)
        goto err;
    if (ret->Ai == NULL && (ret->Ai = BN_new()) == NULL)
        goto err;

    if (e != NULL) {
R
Rich Salz 已提交
241
        BN_free(ret->e);
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282
        ret->e = BN_dup(e);
    }
    if (ret->e == NULL)
        goto err;

    if (bn_mod_exp != NULL)
        ret->bn_mod_exp = bn_mod_exp;
    if (m_ctx != NULL)
        ret->m_ctx = m_ctx;

    do {
        int rv;
        if (!BN_rand_range(ret->A, ret->mod))
            goto err;
        if (!int_bn_mod_inverse(ret->Ai, ret->A, ret->mod, ctx, &rv)) {
            /*
             * this should almost never happen for good RSA keys
             */
            if (rv) {
                if (retry_counter-- == 0) {
                    BNerr(BN_F_BN_BLINDING_CREATE_PARAM,
                          BN_R_TOO_MANY_ITERATIONS);
                    goto err;
                }
            } else
                goto err;
        } else
            break;
    } while (1);

    if (ret->bn_mod_exp != NULL && ret->m_ctx != NULL) {
        if (!ret->bn_mod_exp
            (ret->A, ret->A, ret->e, ret->mod, ctx, ret->m_ctx))
            goto err;
    } else {
        if (!BN_mod_exp(ret->A, ret->A, ret->e, ret->mod, ctx))
            goto err;
    }

    return ret;
 err:
R
Rich Salz 已提交
283
    if (b == NULL) {
284 285 286 287 288
        BN_BLINDING_free(ret);
        ret = NULL;
    }

    return ret;
289
}