rsa_chk.c 6.0 KB
Newer Older
R
Rich Salz 已提交
1
/*
P
Paul Yang 已提交
2
 * Copyright 1999-2017 The OpenSSL Project Authors. All Rights Reserved.
B
Bodo Möller 已提交
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
B
Bodo Möller 已提交
8 9 10 11
 */

#include <openssl/bn.h>
#include <openssl/err.h>
R
Richard Levitte 已提交
12
#include "rsa_locl.h"
B
Bodo Möller 已提交
13

R
Richard Levitte 已提交
14
int RSA_check_key(const RSA *key)
15 16 17
{
    return RSA_check_key_ex(key, NULL);
}
18 19

int RSA_check_key_ex(const RSA *key, BN_GENCB *cb)
20 21 22
{
    BIGNUM *i, *j, *k, *l, *m;
    BN_CTX *ctx;
P
Paul Yang 已提交
23 24
    int ret = 1, ex_primes = 0, idx;
    RSA_PRIME_INFO *pinfo;
25

26 27
    if (key->p == NULL || key->q == NULL || key->n == NULL
            || key->e == NULL || key->d == NULL) {
28 29 30 31
        RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_VALUE_MISSING);
        return 0;
    }

P
Paul Yang 已提交
32
    /* multi-prime? */
33 34 35 36 37 38 39
    if (key->version == RSA_ASN1_VERSION_MULTI) {
        ex_primes = sk_RSA_PRIME_INFO_num(key->prime_infos);
        if (ex_primes <= 0
                || (ex_primes + 2) > rsa_multip_cap(BN_num_bits(key->n))) {
            RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_INVALID_MULTI_PRIME_KEY);
            return 0;
        }
P
Paul Yang 已提交
40 41
    }

42 43 44 45 46 47
    i = BN_new();
    j = BN_new();
    k = BN_new();
    l = BN_new();
    m = BN_new();
    ctx = BN_CTX_new();
48 49
    if (i == NULL || j == NULL || k == NULL || l == NULL
            || m == NULL || ctx == NULL) {
50 51 52 53 54
        ret = -1;
        RSAerr(RSA_F_RSA_CHECK_KEY_EX, ERR_R_MALLOC_FAILURE);
        goto err;
    }

55 56 57 58 59 60 61 62 63
    if (BN_is_one(key->e)) {
        ret = 0;
        RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_BAD_E_VALUE);
    }
    if (!BN_is_odd(key->e)) {
        ret = 0;
        RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_BAD_E_VALUE);
    }

64
    /* p prime? */
65 66
    if (BN_is_prime_ex(key->p, BN_prime_checks, NULL, cb) != 1) {
        ret = 0;
67 68 69 70
        RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_P_NOT_PRIME);
    }

    /* q prime? */
71 72
    if (BN_is_prime_ex(key->q, BN_prime_checks, NULL, cb) != 1) {
        ret = 0;
73 74 75
        RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_Q_NOT_PRIME);
    }

P
Paul Yang 已提交
76 77 78 79 80 81 82 83 84 85
    /* r_i prime? */
    for (idx = 0; idx < ex_primes; idx++) {
        pinfo = sk_RSA_PRIME_INFO_value(key->prime_infos, idx);
        if (BN_is_prime_ex(pinfo->r, BN_prime_checks, NULL, cb) != 1) {
            ret = 0;
            RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_MP_R_NOT_PRIME);
        }
    }

    /* n = p*q * r_3...r_i? */
86
    if (!BN_mul(i, key->p, key->q, ctx)) {
87 88 89
        ret = -1;
        goto err;
    }
P
Paul Yang 已提交
90 91 92 93 94 95 96
    for (idx = 0; idx < ex_primes; idx++) {
        pinfo = sk_RSA_PRIME_INFO_value(key->prime_infos, idx);
        if (!BN_mul(i, i, pinfo->r, ctx)) {
            ret = -1;
            goto err;
        }
    }
97 98
    if (BN_cmp(i, key->n) != 0) {
        ret = 0;
P
Paul Yang 已提交
99 100 101 102 103
        if (ex_primes)
            RSAerr(RSA_F_RSA_CHECK_KEY_EX,
                   RSA_R_N_DOES_NOT_EQUAL_PRODUCT_OF_PRIMES);
        else
            RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_N_DOES_NOT_EQUAL_P_Q);
104 105
    }

P
Paul Yang 已提交
106
    /* d*e = 1  mod \lambda(n)? */
107
    if (!BN_sub(i, key->p, BN_value_one())) {
108 109 110
        ret = -1;
        goto err;
    }
111
    if (!BN_sub(j, key->q, BN_value_one())) {
112 113 114 115
        ret = -1;
        goto err;
    }

P
Paul Yang 已提交
116
    /* now compute k = \lambda(n) = LCM(i, j, r_3 - 1...) */
117
    if (!BN_mul(l, i, j, ctx)) {
118 119 120
        ret = -1;
        goto err;
    }
121
    if (!BN_gcd(m, i, j, ctx)) {
122 123 124
        ret = -1;
        goto err;
    }
P
Paul Yang 已提交
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
    for (idx = 0; idx < ex_primes; idx++) {
        pinfo = sk_RSA_PRIME_INFO_value(key->prime_infos, idx);
        if (!BN_sub(k, pinfo->r, BN_value_one())) {
            ret = -1;
            goto err;
        }
        if (!BN_mul(l, l, k, ctx)) {
            ret = -1;
            goto err;
        }
        if (!BN_gcd(m, m, k, ctx)) {
            ret = -1;
            goto err;
        }
    }
140
    if (!BN_div(k, NULL, l, m, ctx)) { /* remainder is 0 */
141 142 143
        ret = -1;
        goto err;
    }
144
    if (!BN_mod_mul(i, key->d, key->e, k, ctx)) {
145 146 147 148 149 150 151 152 153 154 155
        ret = -1;
        goto err;
    }

    if (!BN_is_one(i)) {
        ret = 0;
        RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_D_E_NOT_CONGRUENT_TO_1);
    }

    if (key->dmp1 != NULL && key->dmq1 != NULL && key->iqmp != NULL) {
        /* dmp1 = d mod (p-1)? */
156
        if (!BN_sub(i, key->p, BN_value_one())) {
157 158 159
            ret = -1;
            goto err;
        }
160
        if (!BN_mod(j, key->d, i, ctx)) {
161 162 163 164 165 166 167 168 169
            ret = -1;
            goto err;
        }
        if (BN_cmp(j, key->dmp1) != 0) {
            ret = 0;
            RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_DMP1_NOT_CONGRUENT_TO_D);
        }

        /* dmq1 = d mod (q-1)? */
170
        if (!BN_sub(i, key->q, BN_value_one())) {
171 172 173
            ret = -1;
            goto err;
        }
174
        if (!BN_mod(j, key->d, i, ctx)) {
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
            ret = -1;
            goto err;
        }
        if (BN_cmp(j, key->dmq1) != 0) {
            ret = 0;
            RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_DMQ1_NOT_CONGRUENT_TO_D);
        }

        /* iqmp = q^-1 mod p? */
        if (!BN_mod_inverse(i, key->q, key->p, ctx)) {
            ret = -1;
            goto err;
        }
        if (BN_cmp(i, key->iqmp) != 0) {
            ret = 0;
            RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_IQMP_NOT_INVERSE_OF_Q);
        }
    }
193

P
Paul Yang 已提交
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
    for (idx = 0; idx < ex_primes; idx++) {
        pinfo = sk_RSA_PRIME_INFO_value(key->prime_infos, idx);
        /* d_i = d mod (r_i - 1)? */
        if (!BN_sub(i, pinfo->r, BN_value_one())) {
            ret = -1;
            goto err;
        }
        if (!BN_mod(j, key->d, i, ctx)) {
            ret = -1;
            goto err;
        }
        if (BN_cmp(j, pinfo->d) != 0) {
            ret = 0;
            RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_MP_EXPONENT_NOT_CONGRUENT_TO_D);
        }
        /* t_i = R_i ^ -1 mod r_i ? */
        if (!BN_mod_inverse(i, pinfo->pp, pinfo->r, ctx)) {
            ret = -1;
            goto err;
        }
        if (BN_cmp(i, pinfo->t) != 0) {
            ret = 0;
            RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_MP_COEFFICIENT_NOT_INVERSE_OF_R);
        }
    }

B
Bodo Möller 已提交
220
 err:
R
Rich Salz 已提交
221 222 223 224 225 226
    BN_free(i);
    BN_free(j);
    BN_free(k);
    BN_free(l);
    BN_free(m);
    BN_CTX_free(ctx);
227
    return ret;
228
}