RT2676: Reject RSA eponent if even or 1
[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 ret = 1;
24
25     if (key->p == NULL || key->q == NULL || key->n == NULL
26             || key->e == NULL || key->d == NULL) {
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     if (BN_is_one(key->e)) {
45         ret = 0;
46         RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_BAD_E_VALUE);
47     }
48     if (!BN_is_odd(key->e)) {
49         ret = 0;
50         RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_BAD_E_VALUE);
51     }
52
53     /* p prime? */
54     if (BN_is_prime_ex(key->p, BN_prime_checks, NULL, cb) != 1) {
55         ret = 0;
56         RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_P_NOT_PRIME);
57     }
58
59     /* q prime? */
60     if (BN_is_prime_ex(key->q, BN_prime_checks, NULL, cb) != 1) {
61         ret = 0;
62         RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_Q_NOT_PRIME);
63     }
64
65     /* n = p*q? */
66     if (!BN_mul(i, key->p, key->q, ctx)) {
67         ret = -1;
68         goto err;
69     }
70     if (BN_cmp(i, key->n) != 0) {
71         ret = 0;
72         RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_N_DOES_NOT_EQUAL_P_Q);
73     }
74
75     /* d*e = 1  mod lcm(p-1,q-1)? */
76     if (!BN_sub(i, key->p, BN_value_one())) {
77         ret = -1;
78         goto err;
79     }
80     if (!BN_sub(j, key->q, BN_value_one())) {
81         ret = -1;
82         goto err;
83     }
84
85     /* now compute k = lcm(i,j) */
86     if (!BN_mul(l, i, j, ctx)) {
87         ret = -1;
88         goto err;
89     }
90     if (!BN_gcd(m, i, j, ctx)) {
91         ret = -1;
92         goto err;
93     }
94     if (!BN_div(k, NULL, l, m, ctx)) { /* remainder is 0 */
95         ret = -1;
96         goto err;
97     }
98     if (!BN_mod_mul(i, key->d, key->e, k, ctx)) {
99         ret = -1;
100         goto err;
101     }
102
103     if (!BN_is_one(i)) {
104         ret = 0;
105         RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_D_E_NOT_CONGRUENT_TO_1);
106     }
107
108     if (key->dmp1 != NULL && key->dmq1 != NULL && key->iqmp != NULL) {
109         /* dmp1 = d mod (p-1)? */
110         if (!BN_sub(i, key->p, BN_value_one())) {
111             ret = -1;
112             goto err;
113         }
114         if (!BN_mod(j, key->d, i, ctx)) {
115             ret = -1;
116             goto err;
117         }
118         if (BN_cmp(j, key->dmp1) != 0) {
119             ret = 0;
120             RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_DMP1_NOT_CONGRUENT_TO_D);
121         }
122
123         /* dmq1 = d mod (q-1)? */
124         if (!BN_sub(i, key->q, BN_value_one())) {
125             ret = -1;
126             goto err;
127         }
128         if (!BN_mod(j, key->d, i, ctx)) {
129             ret = -1;
130             goto err;
131         }
132         if (BN_cmp(j, key->dmq1) != 0) {
133             ret = 0;
134             RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_DMQ1_NOT_CONGRUENT_TO_D);
135         }
136
137         /* iqmp = q^-1 mod p? */
138         if (!BN_mod_inverse(i, key->q, key->p, ctx)) {
139             ret = -1;
140             goto err;
141         }
142         if (BN_cmp(i, key->iqmp) != 0) {
143             ret = 0;
144             RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_IQMP_NOT_INVERSE_OF_Q);
145         }
146     }
147
148  err:
149     BN_free(i);
150     BN_free(j);
151     BN_free(k);
152     BN_free(l);
153     BN_free(m);
154     BN_CTX_free(ctx);
155     return ret;
156 }