Copyright consolidation 08/10
[oweals/openssl.git] / crypto / rsa / rsa_chk.c
1 /*
2  * Copyright 1999-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/bn.h>
11 #include <openssl/err.h>
12 #include "rsa_locl.h"
13
14 int RSA_check_key(const RSA *key)
15 {
16     return RSA_check_key_ex(key, NULL);
17 }
18
19 int RSA_check_key_ex(const RSA *key, BN_GENCB *cb)
20 {
21     BIGNUM *i, *j, *k, *l, *m;
22     BN_CTX *ctx;
23     int r;
24     int ret = 1;
25
26     if (!key->p || !key->q || !key->n || !key->e || !key->d) {
27         RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_VALUE_MISSING);
28         return 0;
29     }
30
31     i = BN_new();
32     j = BN_new();
33     k = BN_new();
34     l = BN_new();
35     m = BN_new();
36     ctx = BN_CTX_new();
37     if (i == NULL || j == NULL || k == NULL || l == NULL ||
38         m == NULL || ctx == NULL) {
39         ret = -1;
40         RSAerr(RSA_F_RSA_CHECK_KEY_EX, ERR_R_MALLOC_FAILURE);
41         goto err;
42     }
43
44     /* p prime? */
45     r = BN_is_prime_ex(key->p, BN_prime_checks, NULL, cb);
46     if (r != 1) {
47         ret = r;
48         if (r != 0)
49             goto err;
50         RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_P_NOT_PRIME);
51     }
52
53     /* q prime? */
54     r = BN_is_prime_ex(key->q, BN_prime_checks, NULL, cb);
55     if (r != 1) {
56         ret = r;
57         if (r != 0)
58             goto err;
59         RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_Q_NOT_PRIME);
60     }
61
62     /* n = p*q? */
63     r = BN_mul(i, key->p, key->q, ctx);
64     if (!r) {
65         ret = -1;
66         goto err;
67     }
68
69     if (BN_cmp(i, key->n) != 0) {
70         ret = 0;
71         RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_N_DOES_NOT_EQUAL_P_Q);
72     }
73
74     /* d*e = 1  mod lcm(p-1,q-1)? */
75
76     r = BN_sub(i, key->p, BN_value_one());
77     if (!r) {
78         ret = -1;
79         goto err;
80     }
81     r = BN_sub(j, key->q, BN_value_one());
82     if (!r) {
83         ret = -1;
84         goto err;
85     }
86
87     /* now compute k = lcm(i,j) */
88     r = BN_mul(l, i, j, ctx);
89     if (!r) {
90         ret = -1;
91         goto err;
92     }
93     r = BN_gcd(m, i, j, ctx);
94     if (!r) {
95         ret = -1;
96         goto err;
97     }
98     r = BN_div(k, NULL, l, m, ctx); /* remainder is 0 */
99     if (!r) {
100         ret = -1;
101         goto err;
102     }
103
104     r = BN_mod_mul(i, key->d, key->e, k, ctx);
105     if (!r) {
106         ret = -1;
107         goto err;
108     }
109
110     if (!BN_is_one(i)) {
111         ret = 0;
112         RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_D_E_NOT_CONGRUENT_TO_1);
113     }
114
115     if (key->dmp1 != NULL && key->dmq1 != NULL && key->iqmp != NULL) {
116         /* dmp1 = d mod (p-1)? */
117         r = BN_sub(i, key->p, BN_value_one());
118         if (!r) {
119             ret = -1;
120             goto err;
121         }
122
123         r = BN_mod(j, key->d, i, ctx);
124         if (!r) {
125             ret = -1;
126             goto err;
127         }
128
129         if (BN_cmp(j, key->dmp1) != 0) {
130             ret = 0;
131             RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_DMP1_NOT_CONGRUENT_TO_D);
132         }
133
134         /* dmq1 = d mod (q-1)? */
135         r = BN_sub(i, key->q, BN_value_one());
136         if (!r) {
137             ret = -1;
138             goto err;
139         }
140
141         r = BN_mod(j, key->d, i, ctx);
142         if (!r) {
143             ret = -1;
144             goto err;
145         }
146
147         if (BN_cmp(j, key->dmq1) != 0) {
148             ret = 0;
149             RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_DMQ1_NOT_CONGRUENT_TO_D);
150         }
151
152         /* iqmp = q^-1 mod p? */
153         if (!BN_mod_inverse(i, key->q, key->p, ctx)) {
154             ret = -1;
155             goto err;
156         }
157
158         if (BN_cmp(i, key->iqmp) != 0) {
159             ret = 0;
160             RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_IQMP_NOT_INVERSE_OF_Q);
161         }
162     }
163
164  err:
165     BN_free(i);
166     BN_free(j);
167     BN_free(k);
168     BN_free(l);
169     BN_free(m);
170     BN_CTX_free(ctx);
171     return (ret);
172 }