1 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
2 | * All rights reserved. |
3 | * |
4 | * This package is an SSL implementation written |
5 | * by Eric Young (eay@cryptsoft.com). |
6 | * The implementation was written so as to conform with Netscapes SSL. |
7 | * |
8 | * This library is free for commercial and non-commercial use as long as |
9 | * the following conditions are aheared to. The following conditions |
10 | * apply to all code found in this distribution, be it the RC4, RSA, |
11 | * lhash, DES, etc., code; not just the SSL code. The SSL documentation |
12 | * included with this distribution is covered by the same copyright terms |
13 | * except that the holder is Tim Hudson (tjh@cryptsoft.com). |
14 | * |
15 | * Copyright remains Eric Young's, and as such any Copyright notices in |
16 | * the code are not to be removed. |
17 | * If this package is used in a product, Eric Young should be given attribution |
18 | * as the author of the parts of the library used. |
19 | * This can be in the form of a textual message at program startup or |
20 | * in documentation (online or textual) provided with the package. |
21 | * |
22 | * Redistribution and use in source and binary forms, with or without |
23 | * modification, are permitted provided that the following conditions |
24 | * are met: |
25 | * 1. Redistributions of source code must retain the copyright |
26 | * notice, this list of conditions and the following disclaimer. |
27 | * 2. Redistributions in binary form must reproduce the above copyright |
28 | * notice, this list of conditions and the following disclaimer in the |
29 | * documentation and/or other materials provided with the distribution. |
30 | * 3. All advertising materials mentioning features or use of this software |
31 | * must display the following acknowledgement: |
32 | * "This product includes cryptographic software written by |
33 | * Eric Young (eay@cryptsoft.com)" |
34 | * The word 'cryptographic' can be left out if the rouines from the library |
35 | * being used are not cryptographic related :-). |
36 | * 4. If you include any Windows specific code (or a derivative thereof) from |
37 | * the apps directory (application code) you must include an acknowledgement: |
38 | * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
39 | * |
40 | * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
41 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
42 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
43 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
44 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
45 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
46 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
47 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
48 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
49 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
50 | * SUCH DAMAGE. |
51 | * |
52 | * The licence and distribution terms for any publically available version or |
53 | * derivative of this code cannot be changed. i.e. this code cannot simply be |
54 | * copied and put under another distribution licence |
55 | * [including the GNU Public Licence.] */ |
56 | |
57 | #include <openssl/dh.h> |
58 | |
59 | #include <openssl/bn.h> |
60 | |
61 | |
62 | int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *out_flags) { |
63 | *out_flags = 0; |
64 | |
65 | BN_CTX *ctx = BN_CTX_new(); |
66 | if (ctx == NULL) { |
67 | return 0; |
68 | } |
69 | BN_CTX_start(ctx); |
70 | |
71 | int ok = 0; |
72 | |
73 | // Check |pub_key| is greater than 1. |
74 | BIGNUM *tmp = BN_CTX_get(ctx); |
75 | if (tmp == NULL || |
76 | !BN_set_word(tmp, 1)) { |
77 | goto err; |
78 | } |
79 | if (BN_cmp(pub_key, tmp) <= 0) { |
80 | *out_flags |= DH_CHECK_PUBKEY_TOO_SMALL; |
81 | } |
82 | |
83 | // Check |pub_key| is less than |dh->p| - 1. |
84 | if (!BN_copy(tmp, dh->p) || |
85 | !BN_sub_word(tmp, 1)) { |
86 | goto err; |
87 | } |
88 | if (BN_cmp(pub_key, tmp) >= 0) { |
89 | *out_flags |= DH_CHECK_PUBKEY_TOO_LARGE; |
90 | } |
91 | |
92 | if (dh->q != NULL) { |
93 | // Check |pub_key|^|dh->q| is 1 mod |dh->p|. This is necessary for RFC 5114 |
94 | // groups which are not safe primes but pick a generator on a prime-order |
95 | // subgroup of size |dh->q|. |
96 | if (!BN_mod_exp_mont(tmp, pub_key, dh->q, dh->p, ctx, NULL)) { |
97 | goto err; |
98 | } |
99 | if (!BN_is_one(tmp)) { |
100 | *out_flags |= DH_CHECK_PUBKEY_INVALID; |
101 | } |
102 | } |
103 | |
104 | ok = 1; |
105 | |
106 | err: |
107 | BN_CTX_end(ctx); |
108 | BN_CTX_free(ctx); |
109 | return ok; |
110 | } |
111 | |
112 | |
113 | int DH_check(const DH *dh, int *out_flags) { |
114 | // Check that p is a safe prime and if g is 2, 3 or 5, check that it is a |
115 | // suitable generator where: |
116 | // for 2, p mod 24 == 11 |
117 | // for 3, p mod 12 == 5 |
118 | // for 5, p mod 10 == 3 or 7 |
119 | // should hold. |
120 | int ok = 0, r; |
121 | BN_CTX *ctx = NULL; |
122 | BN_ULONG l; |
123 | BIGNUM *t1 = NULL, *t2 = NULL; |
124 | |
125 | *out_flags = 0; |
126 | ctx = BN_CTX_new(); |
127 | if (ctx == NULL) { |
128 | goto err; |
129 | } |
130 | BN_CTX_start(ctx); |
131 | t1 = BN_CTX_get(ctx); |
132 | if (t1 == NULL) { |
133 | goto err; |
134 | } |
135 | t2 = BN_CTX_get(ctx); |
136 | if (t2 == NULL) { |
137 | goto err; |
138 | } |
139 | |
140 | if (dh->q) { |
141 | if (BN_cmp(dh->g, BN_value_one()) <= 0) { |
142 | *out_flags |= DH_CHECK_NOT_SUITABLE_GENERATOR; |
143 | } else if (BN_cmp(dh->g, dh->p) >= 0) { |
144 | *out_flags |= DH_CHECK_NOT_SUITABLE_GENERATOR; |
145 | } else { |
146 | // Check g^q == 1 mod p |
147 | if (!BN_mod_exp_mont(t1, dh->g, dh->q, dh->p, ctx, NULL)) { |
148 | goto err; |
149 | } |
150 | if (!BN_is_one(t1)) { |
151 | *out_flags |= DH_CHECK_NOT_SUITABLE_GENERATOR; |
152 | } |
153 | } |
154 | r = BN_is_prime_ex(dh->q, BN_prime_checks, ctx, NULL); |
155 | if (r < 0) { |
156 | goto err; |
157 | } |
158 | if (!r) { |
159 | *out_flags |= DH_CHECK_Q_NOT_PRIME; |
160 | } |
161 | // Check p == 1 mod q i.e. q divides p - 1 |
162 | if (!BN_div(t1, t2, dh->p, dh->q, ctx)) { |
163 | goto err; |
164 | } |
165 | if (!BN_is_one(t2)) { |
166 | *out_flags |= DH_CHECK_INVALID_Q_VALUE; |
167 | } |
168 | if (dh->j && BN_cmp(dh->j, t1)) { |
169 | *out_flags |= DH_CHECK_INVALID_J_VALUE; |
170 | } |
171 | } else if (BN_is_word(dh->g, DH_GENERATOR_2)) { |
172 | l = BN_mod_word(dh->p, 24); |
173 | if (l == (BN_ULONG)-1) { |
174 | goto err; |
175 | } |
176 | if (l != 11) { |
177 | *out_flags |= DH_CHECK_NOT_SUITABLE_GENERATOR; |
178 | } |
179 | } else if (BN_is_word(dh->g, DH_GENERATOR_5)) { |
180 | l = BN_mod_word(dh->p, 10); |
181 | if (l == (BN_ULONG)-1) { |
182 | goto err; |
183 | } |
184 | if (l != 3 && l != 7) { |
185 | *out_flags |= DH_CHECK_NOT_SUITABLE_GENERATOR; |
186 | } |
187 | } else { |
188 | *out_flags |= DH_CHECK_UNABLE_TO_CHECK_GENERATOR; |
189 | } |
190 | |
191 | r = BN_is_prime_ex(dh->p, BN_prime_checks, ctx, NULL); |
192 | if (r < 0) { |
193 | goto err; |
194 | } |
195 | if (!r) { |
196 | *out_flags |= DH_CHECK_P_NOT_PRIME; |
197 | } else if (!dh->q) { |
198 | if (!BN_rshift1(t1, dh->p)) { |
199 | goto err; |
200 | } |
201 | r = BN_is_prime_ex(t1, BN_prime_checks, ctx, NULL); |
202 | if (r < 0) { |
203 | goto err; |
204 | } |
205 | if (!r) { |
206 | *out_flags |= DH_CHECK_P_NOT_SAFE_PRIME; |
207 | } |
208 | } |
209 | ok = 1; |
210 | |
211 | err: |
212 | if (ctx != NULL) { |
213 | BN_CTX_end(ctx); |
214 | BN_CTX_free(ctx); |
215 | } |
216 | return ok; |
217 | } |
218 | |