Fix CVE-2017-6891 in minitasn1 code
[platform/upstream/gnutls.git] / lib / gnutls_srp.c
1 /*
2  * Copyright (C) 2001-2012 Free Software Foundation, Inc.
3  *
4  * Author: Nikos Mavrogiannopoulos
5  *
6  * This file is part of GnuTLS.
7  *
8  * The GnuTLS is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public License
10  * as published by the Free Software Foundation; either version 2.1 of
11  * the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this program.  If not, see <http://www.gnu.org/licenses/>
20  *
21  */
22
23 #include <gnutls_int.h>
24 #include <gnutls_errors.h>
25 #include <auth/srp.h>
26 #include <gnutls_state.h>
27
28 #ifdef ENABLE_SRP
29
30 #include <gnutls_srp.h>
31 #include <auth/srp_passwd.h>
32 #include <gnutls_mpi.h>
33 #include <gnutls_num.h>
34 #include <gnutls_helper.h>
35 #include <algorithms.h>
36 #include <random.h>
37
38 #include "debug.h"
39
40
41 /* Here functions for SRP (like g^x mod n) are defined 
42  */
43
44 static int
45 _gnutls_srp_gx(uint8_t * text, size_t textsize, uint8_t ** result,
46                bigint_t g, bigint_t prime)
47 {
48         bigint_t x, e = NULL;
49         size_t result_size;
50         int ret;
51
52         if (_gnutls_mpi_init_scan_nz(&x, text, textsize)) {
53                 gnutls_assert();
54                 return GNUTLS_E_MPI_SCAN_FAILED;
55         }
56
57         ret = _gnutls_mpi_init(&e);
58         if (ret < 0)
59                 goto cleanup;
60
61         /* e = g^x mod prime (n) */
62         ret = _gnutls_mpi_powm(e, g, x, prime);
63         if (ret < 0)
64                 goto cleanup;
65
66         ret = _gnutls_mpi_print(e, NULL, &result_size);
67         if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER) {
68                 *result = gnutls_malloc(result_size);
69                 if ((*result) == NULL) {
70                         ret = GNUTLS_E_MEMORY_ERROR;
71                         goto cleanup;
72                 }
73
74                 ret = _gnutls_mpi_print(e, *result, &result_size);
75                 if (ret < 0)
76                         goto cleanup;
77
78                 ret = result_size;
79         } else {
80                 gnutls_assert();
81                 ret = GNUTLS_E_MPI_PRINT_FAILED;
82         }
83
84 cleanup:
85         _gnutls_mpi_release(&e);
86         _gnutls_mpi_release(&x);
87
88         return ret;
89
90 }
91
92
93 /****************
94  * Choose a random value b and calculate B = (k* v + g^b) % N.
95  * where k == SHA1(N|g)
96  * Return: B and if ret_b is not NULL b.
97  */
98 bigint_t
99 _gnutls_calc_srp_B(bigint_t * ret_b, bigint_t g, bigint_t n, bigint_t v)
100 {
101         bigint_t tmpB = NULL, tmpV = NULL;
102         bigint_t b = NULL, B = NULL, k = NULL;
103         int ret;
104
105         /* calculate:  B = (k*v + g^b) % N 
106          */
107         ret = _gnutls_mpi_init_multi(&tmpV, &tmpB, &B, &b, NULL);
108         if (ret < 0)
109                 return NULL;
110
111         _gnutls_mpi_random_modp(b, n, GNUTLS_RND_RANDOM);
112
113         k = _gnutls_calc_srp_u(n, g, n);
114         if (k == NULL) {
115                 gnutls_assert();
116                 goto error;
117         }
118
119         ret = _gnutls_mpi_mulm(tmpV, k, v, n);
120         if (ret < 0) {
121                 gnutls_assert();
122                 goto error;
123         }
124
125         ret = _gnutls_mpi_powm(tmpB, g, b, n);
126         if (ret < 0) {
127                 gnutls_assert();
128                 goto error;
129         }
130
131         ret = _gnutls_mpi_addm(B, tmpV, tmpB, n);
132         if (ret < 0) {
133                 gnutls_assert();
134                 goto error;
135         }
136
137         _gnutls_mpi_release(&k);
138         _gnutls_mpi_release(&tmpB);
139         _gnutls_mpi_release(&tmpV);
140
141         if (ret_b)
142                 *ret_b = b;
143         else
144                 _gnutls_mpi_release(&b);
145
146         return B;
147
148       error:
149         _gnutls_mpi_release(&b);
150         _gnutls_mpi_release(&B);
151         _gnutls_mpi_release(&k);
152         _gnutls_mpi_release(&tmpB);
153         _gnutls_mpi_release(&tmpV);
154         return NULL;
155
156 }
157
158 /* This calculates the SHA1(A | B)
159  * A and B will be left-padded with zeros to fill n_size.
160  */
161 bigint_t _gnutls_calc_srp_u(bigint_t A, bigint_t B, bigint_t n)
162 {
163         size_t b_size, a_size;
164         uint8_t *holder, hd[MAX_HASH_SIZE];
165         size_t holder_size, hash_size, n_size;
166         int ret;
167         bigint_t res;
168
169         /* get the size of n in bytes */
170         _gnutls_mpi_print(n, NULL, &n_size);
171
172         _gnutls_mpi_print(A, NULL, &a_size);
173         _gnutls_mpi_print(B, NULL, &b_size);
174
175         if (a_size > n_size || b_size > n_size) {
176                 gnutls_assert();
177                 return NULL;    /* internal error */
178         }
179
180         holder_size = n_size + n_size;
181
182         holder = gnutls_calloc(1, holder_size);
183         if (holder == NULL)
184                 return NULL;
185
186         _gnutls_mpi_print(A, &holder[n_size - a_size], &a_size);
187         _gnutls_mpi_print(B, &holder[n_size + n_size - b_size], &b_size);
188
189         ret = _gnutls_hash_fast(GNUTLS_DIG_SHA1, holder, holder_size, hd);
190         if (ret < 0) {
191                 gnutls_free(holder);
192                 gnutls_assert();
193                 return NULL;
194         }
195
196         /* convert the bytes of hd to integer
197          */
198         hash_size = 20;         /* SHA */
199         ret = _gnutls_mpi_init_scan_nz(&res, hd, hash_size);
200         gnutls_free(holder);
201
202         if (ret < 0) {
203                 gnutls_assert();
204                 return NULL;
205         }
206
207         return res;
208 }
209
210 /* S = (A * v^u) ^ b % N 
211  * this is our shared key (server premaster secret)
212  */
213 bigint_t
214 _gnutls_calc_srp_S1(bigint_t A, bigint_t b, bigint_t u, bigint_t v,
215                     bigint_t n)
216 {
217         bigint_t tmp1 = NULL, tmp2 = NULL;
218         bigint_t S = NULL;
219         int ret;
220
221         ret = _gnutls_mpi_init_multi(&S, &tmp1, &tmp2, NULL);
222         if (ret < 0)
223                 return NULL;
224
225         ret = _gnutls_mpi_powm(tmp1, v, u, n);
226         if (ret < 0) {
227                 gnutls_assert();
228                 goto error;
229         }
230
231         ret = _gnutls_mpi_mulm(tmp2, A, tmp1, n);
232         if (ret < 0) {
233                 gnutls_assert();
234                 goto error;
235         }
236
237         _gnutls_mpi_powm(S, tmp2, b, n);
238
239         _gnutls_mpi_release(&tmp1);
240         _gnutls_mpi_release(&tmp2);
241
242         return S;
243
244 error:
245         _gnutls_mpi_release(&S);
246         _gnutls_mpi_release(&tmp1);
247         _gnutls_mpi_release(&tmp2);
248         return NULL;
249 }
250
251 /* A = g^a % N 
252  * returns A and a (which is random)
253  */
254 bigint_t _gnutls_calc_srp_A(bigint_t * a, bigint_t g, bigint_t n)
255 {
256         bigint_t tmpa;
257         bigint_t A;
258         int ret;
259
260         ret = _gnutls_mpi_init_multi(&A, &tmpa, NULL);
261         if (ret < 0) {
262                 gnutls_assert();
263                 return NULL;
264         }
265
266         _gnutls_mpi_random_modp(tmpa, n, GNUTLS_RND_RANDOM);
267
268         ret = _gnutls_mpi_powm(A, g, tmpa, n);
269         if (ret < 0)
270                 goto error;
271
272         if (a != NULL)
273                 *a = tmpa;
274         else
275                 _gnutls_mpi_release(&tmpa);
276
277         return A;
278 error:
279         _gnutls_mpi_release(&tmpa);
280         _gnutls_mpi_release(&A);
281         return NULL;
282 }
283
284 /* generate x = SHA(s | SHA(U | ":" | p))
285  * The output is exactly 20 bytes
286  */
287 static int
288 _gnutls_calc_srp_sha(const char *username, const char *password,
289                      uint8_t * salt, int salt_size, size_t * size,
290                      void *digest)
291 {
292         digest_hd_st td;
293         uint8_t res[MAX_HASH_SIZE];
294         int ret;
295         const mac_entry_st *me = mac_to_entry(GNUTLS_MAC_SHA1);
296
297         *size = 20;
298
299         ret = _gnutls_hash_init(&td, me);
300         if (ret < 0) {
301                 return GNUTLS_E_MEMORY_ERROR;
302         }
303         _gnutls_hash(&td, username, strlen(username));
304         _gnutls_hash(&td, ":", 1);
305         _gnutls_hash(&td, password, strlen(password));
306
307         _gnutls_hash_deinit(&td, res);
308
309         ret = _gnutls_hash_init(&td, me);
310         if (ret < 0) {
311                 return GNUTLS_E_MEMORY_ERROR;
312         }
313
314         _gnutls_hash(&td, salt, salt_size);
315         _gnutls_hash(&td, res, 20);     /* 20 bytes is the output of sha1 */
316
317         _gnutls_hash_deinit(&td, digest);
318
319         return 0;
320 }
321
322 int
323 _gnutls_calc_srp_x(char *username, char *password, uint8_t * salt,
324                    size_t salt_size, size_t * size, void *digest)
325 {
326
327         return _gnutls_calc_srp_sha(username, password, salt,
328                                     salt_size, size, digest);
329 }
330
331
332 /* S = (B - k*g^x) ^ (a + u * x) % N
333  * this is our shared key (client premaster secret)
334  */
335 bigint_t
336 _gnutls_calc_srp_S2(bigint_t B, bigint_t g, bigint_t x, bigint_t a,
337                     bigint_t u, bigint_t n)
338 {
339         bigint_t S = NULL, tmp1 = NULL, tmp2 = NULL;
340         bigint_t tmp4 = NULL, tmp3 = NULL, k = NULL;
341         int ret;
342
343         ret = _gnutls_mpi_init_multi(&S, &tmp1, &tmp2, &tmp3, &tmp4, NULL);
344         if (ret < 0)
345                 return NULL;
346
347         k = _gnutls_calc_srp_u(n, g, n);
348         if (k == NULL) {
349                 gnutls_assert();
350                 goto freeall;
351         }
352
353         ret = _gnutls_mpi_powm(tmp1, g, x, n);  /* g^x */
354         if (ret < 0) {
355                 gnutls_assert();
356                 goto freeall;
357         }
358
359         ret = _gnutls_mpi_mulm(tmp3, tmp1, k, n);       /* k*g^x mod n */
360         if (ret < 0) {
361                 gnutls_assert();
362                 goto freeall;
363         }
364
365         ret = _gnutls_mpi_subm(tmp2, B, tmp3, n);
366         if (ret < 0) {
367                 gnutls_assert();
368                 goto freeall;
369         }
370
371         ret = _gnutls_mpi_mul(tmp1, u, x);
372         if (ret < 0) {
373                 gnutls_assert();
374                 goto freeall;
375         }
376
377         ret = _gnutls_mpi_add(tmp4, a, tmp1);
378         if (ret < 0) {
379                 gnutls_assert();
380                 goto freeall;
381         }
382
383         ret = _gnutls_mpi_powm(S, tmp2, tmp4, n);
384         if (ret < 0) {
385                 gnutls_assert();
386                 goto freeall;
387         }
388
389         _gnutls_mpi_release(&tmp1);
390         _gnutls_mpi_release(&tmp2);
391         _gnutls_mpi_release(&tmp3);
392         _gnutls_mpi_release(&tmp4);
393         _gnutls_mpi_release(&k);
394
395         return S;
396
397       freeall:
398         _gnutls_mpi_release(&k);
399         _gnutls_mpi_release(&tmp1);
400         _gnutls_mpi_release(&tmp2);
401         _gnutls_mpi_release(&tmp3);
402         _gnutls_mpi_release(&tmp4);
403         _gnutls_mpi_release(&S);
404         return NULL;
405 }
406
407 /**
408  * gnutls_srp_free_client_credentials:
409  * @sc: is a #gnutls_srp_client_credentials_t structure.
410  *
411  * This structure is complex enough to manipulate directly thus
412  * this helper function is provided in order to free (deallocate) it.
413  **/
414 void gnutls_srp_free_client_credentials(gnutls_srp_client_credentials_t sc)
415 {
416         gnutls_free(sc->username);
417         gnutls_free(sc->password);
418         gnutls_free(sc);
419 }
420
421 /**
422  * gnutls_srp_allocate_client_credentials:
423  * @sc: is a pointer to a #gnutls_srp_server_credentials_t structure.
424  *
425  * This structure is complex enough to manipulate directly thus
426  * this helper function is provided in order to allocate it.
427  *
428  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or an
429  *   error code.
430  **/
431 int
432 gnutls_srp_allocate_client_credentials(gnutls_srp_client_credentials_t *
433                                        sc)
434 {
435         *sc = gnutls_calloc(1, sizeof(srp_client_credentials_st));
436
437         if (*sc == NULL)
438                 return GNUTLS_E_MEMORY_ERROR;
439
440         return 0;
441 }
442
443 /**
444  * gnutls_srp_set_client_credentials:
445  * @res: is a #gnutls_srp_client_credentials_t structure.
446  * @username: is the user's userid
447  * @password: is the user's password
448  *
449  * This function sets the username and password, in a
450  * #gnutls_srp_client_credentials_t structure.  Those will be used in
451  * SRP authentication.  @username and @password should be ASCII
452  * strings or UTF-8 strings prepared using the "SASLprep" profile of
453  * "stringprep".
454  *
455  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or an
456  *   error code.
457  **/
458 int
459 gnutls_srp_set_client_credentials(gnutls_srp_client_credentials_t res,
460                                   const char *username,
461                                   const char *password)
462 {
463
464         if (username == NULL || password == NULL) {
465                 gnutls_assert();
466                 return GNUTLS_E_INVALID_REQUEST;
467         }
468
469         res->username = gnutls_strdup(username);
470         if (res->username == NULL)
471                 return GNUTLS_E_MEMORY_ERROR;
472
473         res->password = gnutls_strdup(password);
474         if (res->password == NULL) {
475                 gnutls_free(res->username);
476                 return GNUTLS_E_MEMORY_ERROR;
477         }
478
479         return 0;
480 }
481
482 /**
483  * gnutls_srp_free_server_credentials:
484  * @sc: is a #gnutls_srp_server_credentials_t structure.
485  *
486  * This structure is complex enough to manipulate directly thus
487  * this helper function is provided in order to free (deallocate) it.
488  **/
489 void gnutls_srp_free_server_credentials(gnutls_srp_server_credentials_t sc)
490 {
491         gnutls_free(sc->password_file);
492         gnutls_free(sc->password_conf_file);
493         _gnutls_free_datum(&sc->fake_salt_seed);
494
495         gnutls_free(sc);
496 }
497
498 /* Size of the default (random) seed if
499  * gnutls_srp_set_server_fake_salt_seed() is not called to set
500  * a seed.
501  */
502 #define DEFAULT_FAKE_SALT_SEED_SIZE 20
503
504 /* Size of the fake salts generated if
505  * gnutls_srp_set_server_fake_salt_seed() is not called to set
506  * another size.
507  */
508 #define DEFAULT_FAKE_SALT_SIZE 16
509
510 /**
511  * gnutls_srp_allocate_server_credentials:
512  * @sc: is a pointer to a #gnutls_srp_server_credentials_t structure.
513  *
514  * This structure is complex enough to manipulate directly thus this
515  * helper function is provided in order to allocate it.
516  *
517  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or an
518  *   error code.
519  **/
520 int
521 gnutls_srp_allocate_server_credentials(gnutls_srp_server_credentials_t *
522                                        sc)
523 {
524         int ret;
525         *sc = gnutls_calloc(1, sizeof(srp_server_cred_st));
526
527         if (*sc == NULL)
528                 return GNUTLS_E_MEMORY_ERROR;
529
530         (*sc)->fake_salt_seed.size = DEFAULT_FAKE_SALT_SEED_SIZE;
531         (*sc)->fake_salt_seed.data = gnutls_malloc(
532                                         DEFAULT_FAKE_SALT_SEED_SIZE);
533         if ((*sc)->fake_salt_seed.data == NULL) {
534                 ret = GNUTLS_E_MEMORY_ERROR;
535                 gnutls_assert();
536                 goto cleanup;
537         }
538
539         ret = _gnutls_rnd(GNUTLS_RND_RANDOM, (*sc)->fake_salt_seed.data,
540                                 DEFAULT_FAKE_SALT_SEED_SIZE);
541
542         if (ret < 0) {
543                 gnutls_assert();
544                 goto cleanup;
545         }
546
547         (*sc)->fake_salt_length = DEFAULT_FAKE_SALT_SIZE;
548         return 0;
549
550 cleanup:
551         _gnutls_free_datum(&(*sc)->fake_salt_seed);
552         gnutls_free(*sc);
553         return ret;
554 }
555
556 /**
557  * gnutls_srp_set_server_credentials_file:
558  * @res: is a #gnutls_srp_server_credentials_t structure.
559  * @password_file: is the SRP password file (tpasswd)
560  * @password_conf_file: is the SRP password conf file (tpasswd.conf)
561  *
562  * This function sets the password files, in a
563  * #gnutls_srp_server_credentials_t structure.  Those password files
564  * hold usernames and verifiers and will be used for SRP
565  * authentication.
566  *
567  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or an
568  *   error code.
569  **/
570 int
571 gnutls_srp_set_server_credentials_file(gnutls_srp_server_credentials_t res,
572                                        const char *password_file,
573                                        const char *password_conf_file)
574 {
575
576         if (password_file == NULL || password_conf_file == NULL) {
577                 gnutls_assert();
578                 return GNUTLS_E_INVALID_REQUEST;
579         }
580
581         /* Check if the files can be opened */
582         if (_gnutls_file_exists(password_file) != 0) {
583                 gnutls_assert();
584                 return GNUTLS_E_FILE_ERROR;
585         }
586
587         if (_gnutls_file_exists(password_conf_file) != 0) {
588                 gnutls_assert();
589                 return GNUTLS_E_FILE_ERROR;
590         }
591
592         res->password_file = gnutls_strdup(password_file);
593         if (res->password_file == NULL) {
594                 gnutls_assert();
595                 return GNUTLS_E_MEMORY_ERROR;
596         }
597
598         res->password_conf_file = gnutls_strdup(password_conf_file);
599         if (res->password_conf_file == NULL) {
600                 gnutls_assert();
601                 gnutls_free(res->password_file);
602                 res->password_file = NULL;
603                 return GNUTLS_E_MEMORY_ERROR;
604         }
605
606         return 0;
607 }
608
609
610 /**
611  * gnutls_srp_set_server_credentials_function:
612  * @cred: is a #gnutls_srp_server_credentials_t structure.
613  * @func: is the callback function
614  *
615  * This function can be used to set a callback to retrieve the user's
616  * SRP credentials.  The callback's function form is:
617  *
618  * int (*callback)(gnutls_session_t, const char* username,
619  *  gnutls_datum_t *salt, gnutls_datum_t *verifier, gnutls_datum_t *generator,
620  *  gnutls_datum_t *prime);
621  *
622  * @username contains the actual username.
623  * The @salt, @verifier, @generator and @prime must be filled
624  * in using the gnutls_malloc(). For convenience @prime and @generator
625  * may also be one of the static parameters defined in gnutls.h.
626  *
627  * Initially, the data field is NULL in every #gnutls_datum_t
628  * structure that the callback has to fill in. When the
629  * callback is done GnuTLS deallocates all of those buffers
630  * which are non-NULL, regardless of the return value.
631  *
632  * In order to prevent attackers from guessing valid usernames,
633  * if a user does not exist, g and n values should be filled in
634  * using a random user's parameters. In that case the callback must
635  * return the special value (1).
636  * See #gnutls_srp_set_server_fake_salt_seed too.
637  * If this is not required for your application, return a negative
638  * number from the callback to abort the handshake.
639  *
640  * The callback function will only be called once per handshake.
641  * The callback function should return 0 on success, while
642  * -1 indicates an error.
643  **/
644 void
645 gnutls_srp_set_server_credentials_function(gnutls_srp_server_credentials_t
646                                            cred,
647                                            gnutls_srp_server_credentials_function
648                                            *func)
649 {
650         cred->pwd_callback = func;
651 }
652
653 /**
654  * gnutls_srp_set_client_credentials_function:
655  * @cred: is a #gnutls_srp_server_credentials_t structure.
656  * @func: is the callback function
657  *
658  * This function can be used to set a callback to retrieve the
659  * username and password for client SRP authentication.  The
660  * callback's function form is:
661  *
662  * int (*callback)(gnutls_session_t, char** username, char**password);
663  *
664  * The @username and @password must be allocated using
665  * gnutls_malloc().  @username and @password should be ASCII strings
666  * or UTF-8 strings prepared using the "SASLprep" profile of
667  * "stringprep".
668  *
669  * The callback function will be called once per handshake before the
670  * initial hello message is sent.
671  *
672  * The callback should not return a negative error code the second
673  * time called, since the handshake procedure will be aborted.
674  *
675  * The callback function should return 0 on success.
676  * -1 indicates an error.
677  **/
678 void
679 gnutls_srp_set_client_credentials_function(gnutls_srp_client_credentials_t
680                                            cred,
681                                            gnutls_srp_client_credentials_function
682                                            * func)
683 {
684         cred->get_function = func;
685 }
686
687
688 /**
689  * gnutls_srp_server_get_username:
690  * @session: is a gnutls session
691  *
692  * This function will return the username of the peer.  This should
693  * only be called in case of SRP authentication and in case of a
694  * server.  Returns NULL in case of an error.
695  *
696  * Returns: SRP username of the peer, or NULL in case of error.
697  **/
698 const char *gnutls_srp_server_get_username(gnutls_session_t session)
699 {
700         srp_server_auth_info_t info;
701
702         CHECK_AUTH(GNUTLS_CRD_SRP, NULL);
703
704         info = _gnutls_get_auth_info(session, GNUTLS_CRD_SRP);
705         if (info == NULL)
706                 return NULL;
707         return info->username;
708 }
709
710 /**
711  * gnutls_srp_verifier:
712  * @username: is the user's name
713  * @password: is the user's password
714  * @salt: should be some randomly generated bytes
715  * @generator: is the generator of the group
716  * @prime: is the group's prime
717  * @res: where the verifier will be stored.
718  *
719  * This function will create an SRP verifier, as specified in
720  * RFC2945.  The @prime and @generator should be one of the static
721  * parameters defined in gnutls/gnutls.h or may be generated.
722  *
723  * The verifier will be allocated with @gnutls_malloc() and will be stored in
724  * @res using binary format.
725  *
726  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or an
727  *   error code.
728  **/
729 int
730 gnutls_srp_verifier(const char *username, const char *password,
731                     const gnutls_datum_t * salt,
732                     const gnutls_datum_t * generator,
733                     const gnutls_datum_t * prime, gnutls_datum_t * res)
734 {
735         bigint_t _n, _g;
736         int ret;
737         size_t digest_size = 20, size;
738         uint8_t digest[20];
739
740         ret = _gnutls_calc_srp_sha(username, password, salt->data,
741                                    salt->size, &digest_size, digest);
742         if (ret < 0) {
743                 gnutls_assert();
744                 return ret;
745         }
746
747         size = prime->size;
748         if (_gnutls_mpi_init_scan_nz(&_n, prime->data, size)) {
749                 gnutls_assert();
750                 return GNUTLS_E_MPI_SCAN_FAILED;
751         }
752
753         size = generator->size;
754         if (_gnutls_mpi_init_scan_nz(&_g, generator->data, size)) {
755                 gnutls_assert();
756                 return GNUTLS_E_MPI_SCAN_FAILED;
757         }
758
759         ret = _gnutls_srp_gx(digest, 20, &res->data, _g, _n);
760         if (ret < 0) {
761                 gnutls_assert();
762                 return ret;
763         }
764         res->size = ret;
765
766         return 0;
767 }
768
769 /**
770  * gnutls_srp_set_prime_bits:
771  * @session: is a #gnutls_session_t structure.
772  * @bits: is the number of bits
773  *
774  * This function sets the minimum accepted number of bits, for use in
775  * an SRP key exchange.  If zero, the default 2048 bits will be used.
776  *
777  * In the client side it sets the minimum accepted number of bits.  If
778  * a server sends a prime with less bits than that
779  * %GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER will be returned by the
780  * handshake.
781  *
782  * This function has no effect in server side.
783  *
784  * Since: 2.6.0
785  **/
786 void gnutls_srp_set_prime_bits(gnutls_session_t session, unsigned int bits)
787 {
788         session->internals.srp_prime_bits = bits;
789 }
790
791 /**
792  * gnutls_srp_set_server_fake_salt_seed:
793  * @cred: is a #gnutls_srp_server_credentials_t structure
794  * @seed: is the seed data, only needs to be valid until the function
795  * returns; size of the seed must be greater than zero
796  * @salt_length: is the length of the generated fake salts
797  *
798  * This function sets the seed that is used to generate salts for
799  * invalid (non-existent) usernames.
800  *
801  * In order to prevent attackers from guessing valid usernames,
802  * when a user does not exist gnutls generates a salt and a verifier
803  * and proceeds with the protocol as usual.
804  * The authentication will ultimately fail, but the client cannot tell
805  * whether the username is valid (exists) or invalid.
806  *
807  * If an attacker learns the seed, given a salt (which is part of the
808  * handshake) which was generated when the seed was in use, it can tell
809  * whether or not the authentication failed because of an unknown username.
810  * This seed cannot be used to reveal application data or passwords.
811  *
812  * @salt_length should represent the salt length your application uses.
813  * Generating fake salts longer than 20 bytes is not supported.
814  *
815  * By default the seed is a random value, different each time a
816  * #gnutls_srp_server_credentials_t is allocated and fake salts are
817  * 16 bytes long.
818  *
819  * Since: 3.3.0
820  **/
821 void
822 gnutls_srp_set_server_fake_salt_seed(gnutls_srp_server_credentials_t cred,
823                                      const gnutls_datum_t * seed,
824                                      unsigned int salt_length)
825 {
826         _gnutls_free_datum(&cred->fake_salt_seed);
827         _gnutls_set_datum(&cred->fake_salt_seed, seed->data, seed->size);
828
829         /* Cap the salt length at the output size of the MAC algorithm
830          * we are using to generate the fake salts.
831          */
832         const mac_entry_st * me = mac_to_entry(SRP_FAKE_SALT_MAC);
833         const size_t mac_len = me->output_size;
834
835         cred->fake_salt_length = (salt_length < mac_len ? salt_length : mac_len);
836 }
837
838 #endif                          /* ENABLE_SRP */