xref: /freebsd/crypto/openssl/crypto/srp/srp_lib.c (revision f25b8c9fb4f58cf61adb47d7570abe7caa6d385d)
1 /*
2  * Copyright 2004-2021 The OpenSSL Project Authors. All Rights Reserved.
3  * Copyright (c) 2004, EdelKey Project. All Rights Reserved.
4  *
5  * Licensed under the Apache License 2.0 (the "License").  You may not use
6  * this file except in compliance with the License.  You can obtain a copy
7  * in the file LICENSE in the source distribution or at
8  * https://www.openssl.org/source/license.html
9  *
10  * Originally written by Christophe Renou and Peter Sylvester,
11  * for the EdelKey project.
12  */
13 
14 /* All the SRP APIs in this file are deprecated */
15 #define OPENSSL_SUPPRESS_DEPRECATED
16 
17 #ifndef OPENSSL_NO_SRP
18 #include "internal/cryptlib.h"
19 #include <openssl/sha.h>
20 #include <openssl/srp.h>
21 #include <openssl/evp.h>
22 #include "crypto/bn_srp.h"
23 
24 /* calculate = SHA1(PAD(x) || PAD(y)) */
25 
srp_Calc_xy(const BIGNUM * x,const BIGNUM * y,const BIGNUM * N,OSSL_LIB_CTX * libctx,const char * propq)26 static BIGNUM *srp_Calc_xy(const BIGNUM *x, const BIGNUM *y, const BIGNUM *N,
27     OSSL_LIB_CTX *libctx, const char *propq)
28 {
29     unsigned char digest[SHA_DIGEST_LENGTH];
30     unsigned char *tmp = NULL;
31     int numN = BN_num_bytes(N);
32     BIGNUM *res = NULL;
33     EVP_MD *sha1 = EVP_MD_fetch(libctx, "SHA1", propq);
34 
35     if (sha1 == NULL)
36         return NULL;
37 
38     if (x != N && BN_ucmp(x, N) >= 0)
39         goto err;
40     if (y != N && BN_ucmp(y, N) >= 0)
41         goto err;
42     if ((tmp = OPENSSL_malloc(numN * 2)) == NULL)
43         goto err;
44     if (BN_bn2binpad(x, tmp, numN) < 0
45         || BN_bn2binpad(y, tmp + numN, numN) < 0
46         || !EVP_Digest(tmp, numN * 2, digest, NULL, sha1, NULL))
47         goto err;
48     res = BN_bin2bn(digest, sizeof(digest), NULL);
49 err:
50     EVP_MD_free(sha1);
51     OPENSSL_free(tmp);
52     return res;
53 }
54 
srp_Calc_k(const BIGNUM * N,const BIGNUM * g,OSSL_LIB_CTX * libctx,const char * propq)55 static BIGNUM *srp_Calc_k(const BIGNUM *N, const BIGNUM *g,
56     OSSL_LIB_CTX *libctx,
57     const char *propq)
58 {
59     /* k = SHA1(N | PAD(g)) -- tls-srp RFC 5054 */
60     return srp_Calc_xy(N, g, N, libctx, propq);
61 }
62 
SRP_Calc_u_ex(const BIGNUM * A,const BIGNUM * B,const BIGNUM * N,OSSL_LIB_CTX * libctx,const char * propq)63 BIGNUM *SRP_Calc_u_ex(const BIGNUM *A, const BIGNUM *B, const BIGNUM *N,
64     OSSL_LIB_CTX *libctx, const char *propq)
65 {
66     /* u = SHA1(PAD(A) || PAD(B) ) -- tls-srp RFC 5054 */
67     return srp_Calc_xy(A, B, N, libctx, propq);
68 }
69 
SRP_Calc_u(const BIGNUM * A,const BIGNUM * B,const BIGNUM * N)70 BIGNUM *SRP_Calc_u(const BIGNUM *A, const BIGNUM *B, const BIGNUM *N)
71 {
72     /* u = SHA1(PAD(A) || PAD(B) ) -- tls-srp RFC 5054 */
73     return srp_Calc_xy(A, B, N, NULL, NULL);
74 }
75 
SRP_Calc_server_key(const BIGNUM * A,const BIGNUM * v,const BIGNUM * u,const BIGNUM * b,const BIGNUM * N)76 BIGNUM *SRP_Calc_server_key(const BIGNUM *A, const BIGNUM *v, const BIGNUM *u,
77     const BIGNUM *b, const BIGNUM *N)
78 {
79     BIGNUM *tmp = NULL, *S = NULL;
80     BN_CTX *bn_ctx;
81 
82     if (u == NULL || A == NULL || v == NULL || b == NULL || N == NULL)
83         return NULL;
84 
85     if ((bn_ctx = BN_CTX_new()) == NULL || (tmp = BN_new()) == NULL)
86         goto err;
87 
88     /* S = (A*v**u) ** b */
89 
90     if (!BN_mod_exp(tmp, v, u, N, bn_ctx))
91         goto err;
92     if (!BN_mod_mul(tmp, A, tmp, N, bn_ctx))
93         goto err;
94 
95     S = BN_new();
96     if (S != NULL && !BN_mod_exp(S, tmp, b, N, bn_ctx)) {
97         BN_free(S);
98         S = NULL;
99     }
100 err:
101     BN_CTX_free(bn_ctx);
102     BN_clear_free(tmp);
103     return S;
104 }
105 
SRP_Calc_B_ex(const BIGNUM * b,const BIGNUM * N,const BIGNUM * g,const BIGNUM * v,OSSL_LIB_CTX * libctx,const char * propq)106 BIGNUM *SRP_Calc_B_ex(const BIGNUM *b, const BIGNUM *N, const BIGNUM *g,
107     const BIGNUM *v, OSSL_LIB_CTX *libctx, const char *propq)
108 {
109     BIGNUM *kv = NULL, *gb = NULL;
110     BIGNUM *B = NULL, *k = NULL;
111     BN_CTX *bn_ctx;
112 
113     if (b == NULL || N == NULL || g == NULL || v == NULL || (bn_ctx = BN_CTX_new_ex(libctx)) == NULL)
114         return NULL;
115 
116     if ((kv = BN_new()) == NULL || (gb = BN_new()) == NULL || (B = BN_new()) == NULL)
117         goto err;
118 
119     /* B = g**b + k*v */
120 
121     if (!BN_mod_exp(gb, g, b, N, bn_ctx)
122         || (k = srp_Calc_k(N, g, libctx, propq)) == NULL
123         || !BN_mod_mul(kv, v, k, N, bn_ctx)
124         || !BN_mod_add(B, gb, kv, N, bn_ctx)) {
125         BN_free(B);
126         B = NULL;
127     }
128 err:
129     BN_CTX_free(bn_ctx);
130     BN_clear_free(kv);
131     BN_clear_free(gb);
132     BN_free(k);
133     return B;
134 }
135 
SRP_Calc_B(const BIGNUM * b,const BIGNUM * N,const BIGNUM * g,const BIGNUM * v)136 BIGNUM *SRP_Calc_B(const BIGNUM *b, const BIGNUM *N, const BIGNUM *g,
137     const BIGNUM *v)
138 {
139     return SRP_Calc_B_ex(b, N, g, v, NULL, NULL);
140 }
141 
SRP_Calc_x_ex(const BIGNUM * s,const char * user,const char * pass,OSSL_LIB_CTX * libctx,const char * propq)142 BIGNUM *SRP_Calc_x_ex(const BIGNUM *s, const char *user, const char *pass,
143     OSSL_LIB_CTX *libctx, const char *propq)
144 {
145     unsigned char dig[SHA_DIGEST_LENGTH];
146     EVP_MD_CTX *ctxt;
147     unsigned char *cs = NULL;
148     BIGNUM *res = NULL;
149     EVP_MD *sha1 = NULL;
150 
151     if ((s == NULL) || (user == NULL) || (pass == NULL))
152         return NULL;
153 
154     ctxt = EVP_MD_CTX_new();
155     if (ctxt == NULL)
156         return NULL;
157     if ((cs = OPENSSL_malloc(BN_num_bytes(s))) == NULL)
158         goto err;
159 
160     sha1 = EVP_MD_fetch(libctx, "SHA1", propq);
161     if (sha1 == NULL)
162         goto err;
163 
164     if (!EVP_DigestInit_ex(ctxt, sha1, NULL)
165         || !EVP_DigestUpdate(ctxt, user, strlen(user))
166         || !EVP_DigestUpdate(ctxt, ":", 1)
167         || !EVP_DigestUpdate(ctxt, pass, strlen(pass))
168         || !EVP_DigestFinal_ex(ctxt, dig, NULL)
169         || !EVP_DigestInit_ex(ctxt, sha1, NULL))
170         goto err;
171     if (BN_bn2bin(s, cs) < 0)
172         goto err;
173     if (!EVP_DigestUpdate(ctxt, cs, BN_num_bytes(s)))
174         goto err;
175 
176     if (!EVP_DigestUpdate(ctxt, dig, sizeof(dig))
177         || !EVP_DigestFinal_ex(ctxt, dig, NULL))
178         goto err;
179 
180     res = BN_bin2bn(dig, sizeof(dig), NULL);
181 
182 err:
183     EVP_MD_free(sha1);
184     OPENSSL_free(cs);
185     EVP_MD_CTX_free(ctxt);
186     return res;
187 }
188 
SRP_Calc_x(const BIGNUM * s,const char * user,const char * pass)189 BIGNUM *SRP_Calc_x(const BIGNUM *s, const char *user, const char *pass)
190 {
191     return SRP_Calc_x_ex(s, user, pass, NULL, NULL);
192 }
193 
SRP_Calc_A(const BIGNUM * a,const BIGNUM * N,const BIGNUM * g)194 BIGNUM *SRP_Calc_A(const BIGNUM *a, const BIGNUM *N, const BIGNUM *g)
195 {
196     BN_CTX *bn_ctx;
197     BIGNUM *A = NULL;
198 
199     if (a == NULL || N == NULL || g == NULL || (bn_ctx = BN_CTX_new()) == NULL)
200         return NULL;
201 
202     if ((A = BN_new()) != NULL && !BN_mod_exp(A, g, a, N, bn_ctx)) {
203         BN_free(A);
204         A = NULL;
205     }
206     BN_CTX_free(bn_ctx);
207     return A;
208 }
209 
SRP_Calc_client_key_ex(const BIGNUM * N,const BIGNUM * B,const BIGNUM * g,const BIGNUM * x,const BIGNUM * a,const BIGNUM * u,OSSL_LIB_CTX * libctx,const char * propq)210 BIGNUM *SRP_Calc_client_key_ex(const BIGNUM *N, const BIGNUM *B, const BIGNUM *g,
211     const BIGNUM *x, const BIGNUM *a, const BIGNUM *u,
212     OSSL_LIB_CTX *libctx, const char *propq)
213 {
214     BIGNUM *tmp = NULL, *tmp2 = NULL, *tmp3 = NULL, *k = NULL, *K = NULL;
215     BIGNUM *xtmp = NULL;
216     BN_CTX *bn_ctx;
217 
218     if (u == NULL || B == NULL || N == NULL || g == NULL || x == NULL
219         || a == NULL || (bn_ctx = BN_CTX_new_ex(libctx)) == NULL)
220         return NULL;
221 
222     if ((tmp = BN_new()) == NULL || (tmp2 = BN_new()) == NULL || (tmp3 = BN_new()) == NULL || (xtmp = BN_new()) == NULL)
223         goto err;
224 
225     BN_with_flags(xtmp, x, BN_FLG_CONSTTIME);
226     BN_set_flags(tmp, BN_FLG_CONSTTIME);
227     if (!BN_mod_exp(tmp, g, xtmp, N, bn_ctx))
228         goto err;
229     if ((k = srp_Calc_k(N, g, libctx, propq)) == NULL)
230         goto err;
231     if (!BN_mod_mul(tmp2, tmp, k, N, bn_ctx))
232         goto err;
233     if (!BN_mod_sub(tmp, B, tmp2, N, bn_ctx))
234         goto err;
235     if (!BN_mul(tmp3, u, xtmp, bn_ctx))
236         goto err;
237     if (!BN_add(tmp2, a, tmp3))
238         goto err;
239     K = BN_new();
240     if (K != NULL && !BN_mod_exp(K, tmp, tmp2, N, bn_ctx)) {
241         BN_free(K);
242         K = NULL;
243     }
244 
245 err:
246     BN_CTX_free(bn_ctx);
247     BN_free(xtmp);
248     BN_clear_free(tmp);
249     BN_clear_free(tmp2);
250     BN_clear_free(tmp3);
251     BN_free(k);
252     return K;
253 }
254 
SRP_Calc_client_key(const BIGNUM * N,const BIGNUM * B,const BIGNUM * g,const BIGNUM * x,const BIGNUM * a,const BIGNUM * u)255 BIGNUM *SRP_Calc_client_key(const BIGNUM *N, const BIGNUM *B, const BIGNUM *g,
256     const BIGNUM *x, const BIGNUM *a, const BIGNUM *u)
257 {
258     return SRP_Calc_client_key_ex(N, B, g, x, a, u, NULL, NULL);
259 }
260 
SRP_Verify_B_mod_N(const BIGNUM * B,const BIGNUM * N)261 int SRP_Verify_B_mod_N(const BIGNUM *B, const BIGNUM *N)
262 {
263     BIGNUM *r;
264     BN_CTX *bn_ctx;
265     int ret = 0;
266 
267     if (B == NULL || N == NULL || (bn_ctx = BN_CTX_new()) == NULL)
268         return 0;
269 
270     if ((r = BN_new()) == NULL)
271         goto err;
272     /* Checks if B % N == 0 */
273     if (!BN_nnmod(r, B, N, bn_ctx))
274         goto err;
275     ret = !BN_is_zero(r);
276 err:
277     BN_CTX_free(bn_ctx);
278     BN_free(r);
279     return ret;
280 }
281 
SRP_Verify_A_mod_N(const BIGNUM * A,const BIGNUM * N)282 int SRP_Verify_A_mod_N(const BIGNUM *A, const BIGNUM *N)
283 {
284     /* Checks if A % N == 0 */
285     return SRP_Verify_B_mod_N(A, N);
286 }
287 
288 static SRP_gN knowngN[] = {
289     { "8192", &ossl_bn_generator_19, &ossl_bn_group_8192 },
290     { "6144", &ossl_bn_generator_5, &ossl_bn_group_6144 },
291     { "4096", &ossl_bn_generator_5, &ossl_bn_group_4096 },
292     { "3072", &ossl_bn_generator_5, &ossl_bn_group_3072 },
293     { "2048", &ossl_bn_generator_2, &ossl_bn_group_2048 },
294     { "1536", &ossl_bn_generator_2, &ossl_bn_group_1536 },
295     { "1024", &ossl_bn_generator_2, &ossl_bn_group_1024 },
296 };
297 
298 #define KNOWN_GN_NUMBER sizeof(knowngN) / sizeof(SRP_gN)
299 
300 /*
301  * Check if G and N are known parameters. The values have been generated
302  * from the IETF RFC 5054
303  */
SRP_check_known_gN_param(const BIGNUM * g,const BIGNUM * N)304 char *SRP_check_known_gN_param(const BIGNUM *g, const BIGNUM *N)
305 {
306     size_t i;
307     if ((g == NULL) || (N == NULL))
308         return NULL;
309 
310     for (i = 0; i < KNOWN_GN_NUMBER; i++) {
311         if (BN_cmp(knowngN[i].g, g) == 0 && BN_cmp(knowngN[i].N, N) == 0)
312             return knowngN[i].id;
313     }
314     return NULL;
315 }
316 
SRP_get_default_gN(const char * id)317 SRP_gN *SRP_get_default_gN(const char *id)
318 {
319     size_t i;
320 
321     if (id == NULL)
322         return knowngN;
323     for (i = 0; i < KNOWN_GN_NUMBER; i++) {
324         if (strcmp(knowngN[i].id, id) == 0)
325             return knowngN + i;
326     }
327     return NULL;
328 }
329 #endif
330