]>
Commit | Line | Data |
---|---|---|
0f113f3e | 1 | /* |
aa6bb135 | 2 | * Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved. |
edc032b5 | 3 | * |
aa6bb135 RS |
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 | |
edc032b5 | 8 | */ |
aa6bb135 | 9 | |
edc032b5 | 10 | #ifndef OPENSSL_NO_SRP |
b39fc560 | 11 | # include "internal/cryptlib.h" |
dfb56425 | 12 | # include <openssl/sha.h> |
0f113f3e MC |
13 | # include <openssl/srp.h> |
14 | # include <openssl/evp.h> | |
15 | # include "internal/bn_srp.h" | |
edc032b5 BL |
16 | |
17 | static BIGNUM *srp_Calc_k(BIGNUM *N, BIGNUM *g) | |
0f113f3e MC |
18 | { |
19 | /* k = SHA1(N | PAD(g)) -- tls-srp draft 8 */ | |
20 | ||
21 | unsigned char digest[SHA_DIGEST_LENGTH]; | |
22 | unsigned char *tmp; | |
6e59a892 | 23 | EVP_MD_CTX *ctxt = NULL; |
0f113f3e MC |
24 | int longg; |
25 | int longN = BN_num_bytes(N); | |
6e59a892 | 26 | BIGNUM *res = NULL; |
0f113f3e MC |
27 | |
28 | if (BN_ucmp(g, N) >= 0) | |
29 | return NULL; | |
30 | ||
bfb0641f | 31 | ctxt = EVP_MD_CTX_new(); |
6e59a892 | 32 | if (ctxt == NULL) |
0f113f3e | 33 | return NULL; |
6e59a892 RL |
34 | if ((tmp = OPENSSL_malloc(longN)) == NULL) |
35 | goto err; | |
0f113f3e MC |
36 | BN_bn2bin(N, tmp); |
37 | ||
6e59a892 RL |
38 | EVP_DigestInit_ex(ctxt, EVP_sha1(), NULL); |
39 | EVP_DigestUpdate(ctxt, tmp, longN); | |
0f113f3e MC |
40 | |
41 | memset(tmp, 0, longN); | |
42 | longg = BN_bn2bin(g, tmp); | |
43 | /* use the zeros behind to pad on left */ | |
6e59a892 RL |
44 | EVP_DigestUpdate(ctxt, tmp + longg, longN - longg); |
45 | EVP_DigestUpdate(ctxt, tmp, longg); | |
0f113f3e MC |
46 | OPENSSL_free(tmp); |
47 | ||
6e59a892 RL |
48 | EVP_DigestFinal_ex(ctxt, digest, NULL); |
49 | res = BN_bin2bn(digest, sizeof(digest), NULL); | |
50 | err: | |
bfb0641f | 51 | EVP_MD_CTX_free(ctxt); |
6e59a892 | 52 | return res; |
0f113f3e | 53 | } |
edc032b5 BL |
54 | |
55 | BIGNUM *SRP_Calc_u(BIGNUM *A, BIGNUM *B, BIGNUM *N) | |
0f113f3e MC |
56 | { |
57 | /* k = SHA1(PAD(A) || PAD(B) ) -- tls-srp draft 8 */ | |
58 | ||
39d51932 | 59 | BIGNUM *u = NULL; |
0f113f3e | 60 | unsigned char cu[SHA_DIGEST_LENGTH]; |
39d51932 | 61 | unsigned char *cAB = NULL; |
6e59a892 | 62 | EVP_MD_CTX *ctxt = NULL; |
0f113f3e MC |
63 | int longN; |
64 | if ((A == NULL) || (B == NULL) || (N == NULL)) | |
65 | return NULL; | |
66 | ||
67 | if (BN_ucmp(A, N) >= 0 || BN_ucmp(B, N) >= 0) | |
68 | return NULL; | |
69 | ||
70 | longN = BN_num_bytes(N); | |
71 | ||
bfb0641f | 72 | ctxt = EVP_MD_CTX_new(); |
6e59a892 | 73 | if (ctxt == NULL) |
0f113f3e | 74 | return NULL; |
6e59a892 RL |
75 | if ((cAB = OPENSSL_malloc(2 * longN)) == NULL) |
76 | goto err; | |
0f113f3e MC |
77 | |
78 | memset(cAB, 0, longN); | |
79 | ||
6e59a892 RL |
80 | EVP_DigestInit_ex(ctxt, EVP_sha1(), NULL); |
81 | EVP_DigestUpdate(ctxt, cAB + BN_bn2bin(A, cAB + longN), longN); | |
82 | EVP_DigestUpdate(ctxt, cAB + BN_bn2bin(B, cAB + longN), longN); | |
0f113f3e | 83 | OPENSSL_free(cAB); |
6e59a892 | 84 | EVP_DigestFinal_ex(ctxt, cu, NULL); |
0f113f3e | 85 | |
75ebbd9a | 86 | if ((u = BN_bin2bn(cu, sizeof(cu), NULL)) == NULL) |
6e59a892 RL |
87 | goto err; |
88 | if (BN_is_zero(u)) { | |
89 | BN_free(u); | |
90 | u = NULL; | |
91 | } | |
92 | err: | |
bfb0641f | 93 | EVP_MD_CTX_free(ctxt); |
6e59a892 RL |
94 | |
95 | return u; | |
edc032b5 BL |
96 | } |
97 | ||
0f113f3e MC |
98 | BIGNUM *SRP_Calc_server_key(BIGNUM *A, BIGNUM *v, BIGNUM *u, BIGNUM *b, |
99 | BIGNUM *N) | |
100 | { | |
101 | BIGNUM *tmp = NULL, *S = NULL; | |
102 | BN_CTX *bn_ctx; | |
103 | ||
104 | if (u == NULL || A == NULL || v == NULL || b == NULL || N == NULL) | |
105 | return NULL; | |
106 | ||
107 | if ((bn_ctx = BN_CTX_new()) == NULL || | |
108 | (tmp = BN_new()) == NULL || (S = BN_new()) == NULL) | |
109 | goto err; | |
110 | ||
111 | /* S = (A*v**u) ** b */ | |
112 | ||
113 | if (!BN_mod_exp(tmp, v, u, N, bn_ctx)) | |
114 | goto err; | |
115 | if (!BN_mod_mul(tmp, A, tmp, N, bn_ctx)) | |
116 | goto err; | |
117 | if (!BN_mod_exp(S, tmp, b, N, bn_ctx)) | |
118 | goto err; | |
119 | err: | |
120 | BN_CTX_free(bn_ctx); | |
121 | BN_clear_free(tmp); | |
122 | return S; | |
123 | } | |
edc032b5 BL |
124 | |
125 | BIGNUM *SRP_Calc_B(BIGNUM *b, BIGNUM *N, BIGNUM *g, BIGNUM *v) | |
0f113f3e MC |
126 | { |
127 | BIGNUM *kv = NULL, *gb = NULL; | |
128 | BIGNUM *B = NULL, *k = NULL; | |
129 | BN_CTX *bn_ctx; | |
130 | ||
131 | if (b == NULL || N == NULL || g == NULL || v == NULL || | |
132 | (bn_ctx = BN_CTX_new()) == NULL) | |
133 | return NULL; | |
134 | ||
135 | if ((kv = BN_new()) == NULL || | |
136 | (gb = BN_new()) == NULL || (B = BN_new()) == NULL) | |
137 | goto err; | |
138 | ||
139 | /* B = g**b + k*v */ | |
140 | ||
75ebbd9a RS |
141 | if (!BN_mod_exp(gb, g, b, N, bn_ctx) |
142 | || (k = srp_Calc_k(N, g)) == NULL | |
143 | || !BN_mod_mul(kv, v, k, N, bn_ctx) | |
144 | || !BN_mod_add(B, gb, kv, N, bn_ctx)) { | |
0f113f3e MC |
145 | BN_free(B); |
146 | B = NULL; | |
147 | } | |
148 | err: | |
149 | BN_CTX_free(bn_ctx); | |
150 | BN_clear_free(kv); | |
151 | BN_clear_free(gb); | |
152 | BN_free(k); | |
153 | return B; | |
154 | } | |
edc032b5 BL |
155 | |
156 | BIGNUM *SRP_Calc_x(BIGNUM *s, const char *user, const char *pass) | |
0f113f3e MC |
157 | { |
158 | unsigned char dig[SHA_DIGEST_LENGTH]; | |
6e59a892 | 159 | EVP_MD_CTX *ctxt; |
0f113f3e | 160 | unsigned char *cs; |
6e59a892 | 161 | BIGNUM *res = NULL; |
0f113f3e MC |
162 | |
163 | if ((s == NULL) || (user == NULL) || (pass == NULL)) | |
164 | return NULL; | |
165 | ||
bfb0641f | 166 | ctxt = EVP_MD_CTX_new(); |
6e59a892 | 167 | if (ctxt == NULL) |
0f113f3e | 168 | return NULL; |
6e59a892 RL |
169 | if ((cs = OPENSSL_malloc(BN_num_bytes(s))) == NULL) |
170 | goto err; | |
0f113f3e | 171 | |
6e59a892 RL |
172 | EVP_DigestInit_ex(ctxt, EVP_sha1(), NULL); |
173 | EVP_DigestUpdate(ctxt, user, strlen(user)); | |
174 | EVP_DigestUpdate(ctxt, ":", 1); | |
175 | EVP_DigestUpdate(ctxt, pass, strlen(pass)); | |
176 | EVP_DigestFinal_ex(ctxt, dig, NULL); | |
0f113f3e | 177 | |
6e59a892 | 178 | EVP_DigestInit_ex(ctxt, EVP_sha1(), NULL); |
0f113f3e | 179 | BN_bn2bin(s, cs); |
6e59a892 | 180 | EVP_DigestUpdate(ctxt, cs, BN_num_bytes(s)); |
0f113f3e | 181 | OPENSSL_free(cs); |
6e59a892 RL |
182 | EVP_DigestUpdate(ctxt, dig, sizeof(dig)); |
183 | EVP_DigestFinal_ex(ctxt, dig, NULL); | |
0f113f3e | 184 | |
6e59a892 RL |
185 | res = BN_bin2bn(dig, sizeof(dig), NULL); |
186 | err: | |
bfb0641f | 187 | EVP_MD_CTX_free(ctxt); |
6e59a892 | 188 | return res; |
0f113f3e | 189 | } |
edc032b5 BL |
190 | |
191 | BIGNUM *SRP_Calc_A(BIGNUM *a, BIGNUM *N, BIGNUM *g) | |
0f113f3e MC |
192 | { |
193 | BN_CTX *bn_ctx; | |
194 | BIGNUM *A = NULL; | |
195 | ||
23a1d5e9 | 196 | if (a == NULL || N == NULL || g == NULL || (bn_ctx = BN_CTX_new()) == NULL) |
0f113f3e MC |
197 | return NULL; |
198 | ||
199 | if ((A = BN_new()) != NULL && !BN_mod_exp(A, g, a, N, bn_ctx)) { | |
200 | BN_free(A); | |
201 | A = NULL; | |
202 | } | |
203 | BN_CTX_free(bn_ctx); | |
204 | return A; | |
205 | } | |
206 | ||
207 | BIGNUM *SRP_Calc_client_key(BIGNUM *N, BIGNUM *B, BIGNUM *g, BIGNUM *x, | |
208 | BIGNUM *a, BIGNUM *u) | |
209 | { | |
210 | BIGNUM *tmp = NULL, *tmp2 = NULL, *tmp3 = NULL, *k = NULL, *K = NULL; | |
211 | BN_CTX *bn_ctx; | |
212 | ||
213 | if (u == NULL || B == NULL || N == NULL || g == NULL || x == NULL | |
214 | || a == NULL || (bn_ctx = BN_CTX_new()) == NULL) | |
215 | return NULL; | |
216 | ||
217 | if ((tmp = BN_new()) == NULL || | |
218 | (tmp2 = BN_new()) == NULL || | |
23a1d5e9 RS |
219 | (tmp3 = BN_new()) == NULL || |
220 | (K = BN_new()) == NULL) | |
0f113f3e MC |
221 | goto err; |
222 | ||
223 | if (!BN_mod_exp(tmp, g, x, N, bn_ctx)) | |
224 | goto err; | |
75ebbd9a | 225 | if ((k = srp_Calc_k(N, g)) == NULL) |
0f113f3e MC |
226 | goto err; |
227 | if (!BN_mod_mul(tmp2, tmp, k, N, bn_ctx)) | |
228 | goto err; | |
229 | if (!BN_mod_sub(tmp, B, tmp2, N, bn_ctx)) | |
230 | goto err; | |
0f113f3e MC |
231 | if (!BN_mod_mul(tmp3, u, x, N, bn_ctx)) |
232 | goto err; | |
233 | if (!BN_mod_add(tmp2, a, tmp3, N, bn_ctx)) | |
234 | goto err; | |
235 | if (!BN_mod_exp(K, tmp, tmp2, N, bn_ctx)) | |
236 | goto err; | |
237 | ||
238 | err: | |
239 | BN_CTX_free(bn_ctx); | |
240 | BN_clear_free(tmp); | |
241 | BN_clear_free(tmp2); | |
242 | BN_clear_free(tmp3); | |
243 | BN_free(k); | |
244 | return K; | |
245 | } | |
edc032b5 BL |
246 | |
247 | int SRP_Verify_B_mod_N(BIGNUM *B, BIGNUM *N) | |
0f113f3e MC |
248 | { |
249 | BIGNUM *r; | |
250 | BN_CTX *bn_ctx; | |
251 | int ret = 0; | |
252 | ||
253 | if (B == NULL || N == NULL || (bn_ctx = BN_CTX_new()) == NULL) | |
254 | return 0; | |
255 | ||
256 | if ((r = BN_new()) == NULL) | |
257 | goto err; | |
258 | /* Checks if B % N == 0 */ | |
259 | if (!BN_nnmod(r, B, N, bn_ctx)) | |
260 | goto err; | |
261 | ret = !BN_is_zero(r); | |
262 | err: | |
263 | BN_CTX_free(bn_ctx); | |
264 | BN_free(r); | |
265 | return ret; | |
266 | } | |
edc032b5 BL |
267 | |
268 | int SRP_Verify_A_mod_N(BIGNUM *A, BIGNUM *N) | |
0f113f3e MC |
269 | { |
270 | /* Checks if A % N == 0 */ | |
271 | return SRP_Verify_B_mod_N(A, N); | |
272 | } | |
273 | ||
8cf27823 DSH |
274 | static SRP_gN knowngN[] = { |
275 | {"8192", (BIGNUM *)&bn_generator_19, (BIGNUM *)&bn_group_8192}, | |
276 | {"6144", (BIGNUM *)&bn_generator_5, (BIGNUM *)&bn_group_6144}, | |
277 | {"4096", (BIGNUM *)&bn_generator_5, (BIGNUM *)&bn_group_4096}, | |
278 | {"3072", (BIGNUM *)&bn_generator_5, (BIGNUM *)&bn_group_3072}, | |
279 | {"2048", (BIGNUM *)&bn_generator_2, (BIGNUM *)&bn_group_2048}, | |
280 | {"1536", (BIGNUM *)&bn_generator_2, (BIGNUM *)&bn_group_1536}, | |
281 | {"1024", (BIGNUM *)&bn_generator_2, (BIGNUM *)&bn_group_1024}, | |
282 | }; | |
283 | ||
284 | # define KNOWN_GN_NUMBER sizeof(knowngN) / sizeof(SRP_gN) | |
285 | ||
0f113f3e | 286 | /* |
0d4fb843 | 287 | * Check if G and N are known parameters. The values have been generated |
0f113f3e MC |
288 | * from the ietf-tls-srp draft version 8 |
289 | */ | |
290 | char *SRP_check_known_gN_param(BIGNUM *g, BIGNUM *N) | |
291 | { | |
292 | size_t i; | |
293 | if ((g == NULL) || (N == NULL)) | |
294 | return 0; | |
295 | ||
0f113f3e MC |
296 | for (i = 0; i < KNOWN_GN_NUMBER; i++) { |
297 | if (BN_cmp(knowngN[i].g, g) == 0 && BN_cmp(knowngN[i].N, N) == 0) | |
298 | return knowngN[i].id; | |
299 | } | |
300 | return NULL; | |
301 | } | |
edc032b5 | 302 | |
71fa4513 | 303 | SRP_gN *SRP_get_default_gN(const char *id) |
0f113f3e MC |
304 | { |
305 | size_t i; | |
306 | ||
307 | if (id == NULL) | |
308 | return knowngN; | |
309 | for (i = 0; i < KNOWN_GN_NUMBER; i++) { | |
310 | if (strcmp(knowngN[i].id, id) == 0) | |
311 | return knowngN + i; | |
312 | } | |
313 | return NULL; | |
314 | } | |
edc032b5 | 315 | #endif |