If OCSP revocation data are invalid or too old set appropriate verification flags.
[gnutls.git] / lib / gnutls_srp.c
blobf6ae21f2750c88886169026f30d47eb59a74ff8e
1 /*
2 * Copyright (C) 2001-2012 Free Software Foundation, Inc.
4 * Author: Nikos Mavrogiannopoulos
6 * This file is part of GnuTLS.
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 3 of
11 * the License, or (at your option) any later version.
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.
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/>
23 #include <gnutls_int.h>
24 #include <gnutls_errors.h>
25 #include <auth/srp.h>
26 #include <gnutls_state.h>
28 #ifdef ENABLE_SRP
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>
36 #include "debug.h"
39 /* Here functions for SRP (like g^x mod n) are defined
42 static int
43 _gnutls_srp_gx (uint8_t * text, size_t textsize, uint8_t ** result,
44 bigint_t g, bigint_t prime)
46 bigint_t x, e;
47 size_t result_size;
48 int ret;
50 if (_gnutls_mpi_scan_nz (&x, text, textsize))
52 gnutls_assert ();
53 return GNUTLS_E_MPI_SCAN_FAILED;
56 e = _gnutls_mpi_alloc_like (prime);
57 if (e == NULL)
59 gnutls_assert ();
60 _gnutls_mpi_release (&x);
61 return GNUTLS_E_MEMORY_ERROR;
64 /* e = g^x mod prime (n) */
65 _gnutls_mpi_powm (e, g, x, prime);
66 _gnutls_mpi_release (&x);
68 ret = _gnutls_mpi_print (e, NULL, &result_size);
69 if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
71 *result = gnutls_malloc (result_size);
72 if ((*result) == NULL)
73 return GNUTLS_E_MEMORY_ERROR;
75 _gnutls_mpi_print (e, *result, &result_size);
76 ret = result_size;
78 else
80 gnutls_assert ();
81 ret = GNUTLS_E_MPI_PRINT_FAILED;
84 _gnutls_mpi_release (&e);
86 return ret;
91 /****************
92 * Choose a random value b and calculate B = (k* v + g^b) % N.
93 * where k == SHA1(N|g)
94 * Return: B and if ret_b is not NULL b.
96 bigint_t
97 _gnutls_calc_srp_B (bigint_t * ret_b, bigint_t g, bigint_t n, bigint_t v)
99 bigint_t tmpB = NULL, tmpV = NULL;
100 bigint_t b = NULL, B = NULL, k = NULL;
101 int bits;
104 /* calculate: B = (k*v + g^b) % N
106 bits = _gnutls_mpi_get_nbits (n);
108 tmpV = _gnutls_mpi_alloc_like (n);
110 if (tmpV == NULL)
112 gnutls_assert ();
113 goto error;
116 b = _gnutls_mpi_randomize (NULL, bits, GNUTLS_RND_RANDOM);
118 tmpB = _gnutls_mpi_new (bits);
119 if (tmpB == NULL)
121 gnutls_assert ();
122 goto error;
125 B = _gnutls_mpi_new (bits);
126 if (B == NULL)
128 gnutls_assert ();
129 goto error;
132 k = _gnutls_calc_srp_u (n, g, n);
133 if (k == NULL)
135 gnutls_assert ();
136 goto error;
139 _gnutls_mpi_mulm (tmpV, k, v, n);
140 _gnutls_mpi_powm (tmpB, g, b, n);
142 _gnutls_mpi_addm (B, tmpV, tmpB, n);
144 _gnutls_mpi_release (&k);
145 _gnutls_mpi_release (&tmpB);
146 _gnutls_mpi_release (&tmpV);
148 if (ret_b)
149 *ret_b = b;
150 else
151 _gnutls_mpi_release (&b);
153 return B;
155 error:
156 _gnutls_mpi_release (&b);
157 _gnutls_mpi_release (&B);
158 _gnutls_mpi_release (&k);
159 _gnutls_mpi_release (&tmpB);
160 _gnutls_mpi_release (&tmpV);
161 return NULL;
165 /* This calculates the SHA1(A | B)
166 * A and B will be left-padded with zeros to fill n_size.
168 bigint_t
169 _gnutls_calc_srp_u (bigint_t A, bigint_t B, bigint_t n)
171 size_t b_size, a_size;
172 uint8_t *holder, hd[MAX_HASH_SIZE];
173 size_t holder_size, hash_size, n_size;
174 int ret;
175 bigint_t res;
177 /* get the size of n in bytes */
178 _gnutls_mpi_print (n, NULL, &n_size);
180 _gnutls_mpi_print (A, NULL, &a_size);
181 _gnutls_mpi_print (B, NULL, &b_size);
183 if (a_size > n_size || b_size > n_size)
185 gnutls_assert ();
186 return NULL; /* internal error */
189 holder_size = n_size + n_size;
191 holder = gnutls_calloc (1, holder_size);
192 if (holder == NULL)
193 return NULL;
195 _gnutls_mpi_print (A, &holder[n_size - a_size], &a_size);
196 _gnutls_mpi_print (B, &holder[n_size + n_size - b_size], &b_size);
198 ret = _gnutls_hash_fast (GNUTLS_MAC_SHA1, holder, holder_size, hd);
199 if (ret < 0)
201 gnutls_free (holder);
202 gnutls_assert ();
203 return NULL;
206 /* convert the bytes of hd to integer
208 hash_size = 20; /* SHA */
209 ret = _gnutls_mpi_scan_nz (&res, hd, hash_size);
210 gnutls_free (holder);
212 if (ret < 0)
214 gnutls_assert ();
215 return NULL;
218 return res;
221 /* S = (A * v^u) ^ b % N
222 * this is our shared key (server premaster secret)
224 bigint_t
225 _gnutls_calc_srp_S1 (bigint_t A, bigint_t b, bigint_t u, bigint_t v,
226 bigint_t n)
228 bigint_t tmp1 = NULL, tmp2 = NULL;
229 bigint_t S = NULL;
231 S = _gnutls_mpi_alloc_like (n);
232 if (S == NULL)
233 return NULL;
235 tmp1 = _gnutls_mpi_alloc_like (n);
236 tmp2 = _gnutls_mpi_alloc_like (n);
238 if (tmp1 == NULL || tmp2 == NULL)
239 goto freeall;
241 _gnutls_mpi_powm (tmp1, v, u, n);
242 _gnutls_mpi_mulm (tmp2, A, tmp1, n);
243 _gnutls_mpi_powm (S, tmp2, b, n);
245 _gnutls_mpi_release (&tmp1);
246 _gnutls_mpi_release (&tmp2);
248 return S;
250 freeall:
251 _gnutls_mpi_release (&tmp1);
252 _gnutls_mpi_release (&tmp2);
253 return NULL;
256 /* A = g^a % N
257 * returns A and a (which is random)
259 bigint_t
260 _gnutls_calc_srp_A (bigint_t * a, bigint_t g, bigint_t n)
262 bigint_t tmpa;
263 bigint_t A;
264 int bits;
266 bits = _gnutls_mpi_get_nbits (n);
267 tmpa = _gnutls_mpi_randomize (NULL, bits, GNUTLS_RND_RANDOM);
269 A = _gnutls_mpi_new (bits);
270 if (A == NULL)
272 gnutls_assert ();
273 _gnutls_mpi_release (&tmpa);
274 return NULL;
276 _gnutls_mpi_powm (A, g, tmpa, n);
278 if (a != NULL)
279 *a = tmpa;
280 else
281 _gnutls_mpi_release (&tmpa);
283 return A;
286 /* generate x = SHA(s | SHA(U | ":" | p))
287 * The output is exactly 20 bytes
289 static int
290 _gnutls_calc_srp_sha (const char *username, const char *password,
291 uint8_t * salt, int salt_size, size_t * size,
292 void *digest)
294 digest_hd_st td;
295 uint8_t res[MAX_HASH_SIZE];
296 int ret;
298 *size = 20;
300 ret = _gnutls_hash_init (&td, GNUTLS_MAC_SHA1);
301 if (ret < 0)
303 return GNUTLS_E_MEMORY_ERROR;
305 _gnutls_hash (&td, username, strlen (username));
306 _gnutls_hash (&td, ":", 1);
307 _gnutls_hash (&td, password, strlen (password));
309 _gnutls_hash_deinit (&td, res);
311 ret = _gnutls_hash_init (&td, GNUTLS_MAC_SHA1);
312 if (ret < 0)
314 return GNUTLS_E_MEMORY_ERROR;
317 _gnutls_hash (&td, salt, salt_size);
318 _gnutls_hash (&td, res, 20); /* 20 bytes is the output of sha1 */
320 _gnutls_hash_deinit (&td, digest);
322 return 0;
326 _gnutls_calc_srp_x (char *username, char *password, uint8_t * salt,
327 size_t salt_size, size_t * size, void *digest)
330 return _gnutls_calc_srp_sha (username, password, salt,
331 salt_size, size, digest);
335 /* S = (B - k*g^x) ^ (a + u * x) % N
336 * this is our shared key (client premaster secret)
338 bigint_t
339 _gnutls_calc_srp_S2 (bigint_t B, bigint_t g, bigint_t x, bigint_t a,
340 bigint_t u, bigint_t n)
342 bigint_t S = NULL, tmp1 = NULL, tmp2 = NULL;
343 bigint_t tmp4 = NULL, tmp3 = NULL, k = NULL;
345 S = _gnutls_mpi_alloc_like (n);
346 if (S == NULL)
347 return NULL;
349 tmp1 = _gnutls_mpi_alloc_like (n);
350 tmp2 = _gnutls_mpi_alloc_like (n);
351 tmp3 = _gnutls_mpi_alloc_like (n);
352 if (tmp1 == NULL || tmp2 == NULL || tmp3 == NULL)
354 goto freeall;
357 k = _gnutls_calc_srp_u (n, g, n);
358 if (k == NULL)
360 gnutls_assert ();
361 goto freeall;
364 _gnutls_mpi_powm (tmp1, g, x, n); /* g^x */
365 _gnutls_mpi_mulm (tmp3, tmp1, k, n); /* k*g^x mod n */
366 _gnutls_mpi_subm (tmp2, B, tmp3, n);
368 tmp4 = _gnutls_mpi_alloc_like (n);
369 if (tmp4 == NULL)
370 goto freeall;
372 _gnutls_mpi_mul (tmp1, u, x);
373 _gnutls_mpi_add (tmp4, a, tmp1);
374 _gnutls_mpi_powm (S, tmp2, tmp4, n);
376 _gnutls_mpi_release (&tmp1);
377 _gnutls_mpi_release (&tmp2);
378 _gnutls_mpi_release (&tmp3);
379 _gnutls_mpi_release (&tmp4);
380 _gnutls_mpi_release (&k);
382 return S;
384 freeall:
385 _gnutls_mpi_release (&k);
386 _gnutls_mpi_release (&tmp1);
387 _gnutls_mpi_release (&tmp2);
388 _gnutls_mpi_release (&tmp3);
389 _gnutls_mpi_release (&tmp4);
390 _gnutls_mpi_release (&S);
391 return NULL;
395 * gnutls_srp_free_client_credentials:
396 * @sc: is a #gnutls_srp_client_credentials_t structure.
398 * This structure is complex enough to manipulate directly thus
399 * this helper function is provided in order to free (deallocate) it.
401 void
402 gnutls_srp_free_client_credentials (gnutls_srp_client_credentials_t sc)
404 gnutls_free (sc->username);
405 gnutls_free (sc->password);
406 gnutls_free (sc);
410 * gnutls_srp_allocate_client_credentials:
411 * @sc: is a pointer to a #gnutls_srp_server_credentials_t structure.
413 * This structure is complex enough to manipulate directly thus
414 * this helper function is provided in order to allocate it.
416 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or an
417 * error code.
420 gnutls_srp_allocate_client_credentials (gnutls_srp_client_credentials_t * sc)
422 *sc = gnutls_calloc (1, sizeof (srp_client_credentials_st));
424 if (*sc == NULL)
425 return GNUTLS_E_MEMORY_ERROR;
427 return 0;
431 * gnutls_srp_set_client_credentials:
432 * @res: is a #gnutls_srp_client_credentials_t structure.
433 * @username: is the user's userid
434 * @password: is the user's password
436 * This function sets the username and password, in a
437 * #gnutls_srp_client_credentials_t structure. Those will be used in
438 * SRP authentication. @username and @password should be ASCII
439 * strings or UTF-8 strings prepared using the "SASLprep" profile of
440 * "stringprep".
442 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or an
443 * error code.
446 gnutls_srp_set_client_credentials (gnutls_srp_client_credentials_t res,
447 const char *username, const char *password)
450 if (username == NULL || password == NULL)
452 gnutls_assert ();
453 return GNUTLS_E_INVALID_REQUEST;
456 res->username = gnutls_strdup (username);
457 if (res->username == NULL)
458 return GNUTLS_E_MEMORY_ERROR;
460 res->password = gnutls_strdup (password);
461 if (res->password == NULL)
463 gnutls_free (res->username);
464 return GNUTLS_E_MEMORY_ERROR;
467 return 0;
471 * gnutls_srp_free_server_credentials:
472 * @sc: is a #gnutls_srp_server_credentials_t structure.
474 * This structure is complex enough to manipulate directly thus
475 * this helper function is provided in order to free (deallocate) it.
477 void
478 gnutls_srp_free_server_credentials (gnutls_srp_server_credentials_t sc)
480 gnutls_free (sc->password_file);
481 gnutls_free (sc->password_conf_file);
483 gnutls_free (sc);
487 * gnutls_srp_allocate_server_credentials:
488 * @sc: is a pointer to a #gnutls_srp_server_credentials_t structure.
490 * This structure is complex enough to manipulate directly thus this
491 * helper function is provided in order to allocate it.
493 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or an
494 * error code.
497 gnutls_srp_allocate_server_credentials (gnutls_srp_server_credentials_t * sc)
499 *sc = gnutls_calloc (1, sizeof (srp_server_cred_st));
501 if (*sc == NULL)
502 return GNUTLS_E_MEMORY_ERROR;
504 return 0;
508 * gnutls_srp_set_server_credentials_file:
509 * @res: is a #gnutls_srp_server_credentials_t structure.
510 * @password_file: is the SRP password file (tpasswd)
511 * @password_conf_file: is the SRP password conf file (tpasswd.conf)
513 * This function sets the password files, in a
514 * #gnutls_srp_server_credentials_t structure. Those password files
515 * hold usernames and verifiers and will be used for SRP
516 * authentication.
518 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or an
519 * error code.
522 gnutls_srp_set_server_credentials_file (gnutls_srp_server_credentials_t res,
523 const char *password_file,
524 const char *password_conf_file)
527 if (password_file == NULL || password_conf_file == NULL)
529 gnutls_assert ();
530 return GNUTLS_E_INVALID_REQUEST;
533 /* Check if the files can be opened */
534 if (_gnutls_file_exists (password_file) != 0)
536 gnutls_assert ();
537 return GNUTLS_E_FILE_ERROR;
540 if (_gnutls_file_exists (password_conf_file) != 0)
542 gnutls_assert ();
543 return GNUTLS_E_FILE_ERROR;
546 res->password_file = gnutls_strdup (password_file);
547 if (res->password_file == NULL)
549 gnutls_assert ();
550 return GNUTLS_E_MEMORY_ERROR;
553 res->password_conf_file = gnutls_strdup (password_conf_file);
554 if (res->password_conf_file == NULL)
556 gnutls_assert ();
557 gnutls_free (res->password_file);
558 res->password_file = NULL;
559 return GNUTLS_E_MEMORY_ERROR;
562 return 0;
567 * gnutls_srp_set_server_credentials_function:
568 * @cred: is a #gnutls_srp_server_credentials_t structure.
569 * @func: is the callback function
571 * This function can be used to set a callback to retrieve the user's
572 * SRP credentials. The callback's function form is:
574 * int (*callback)(gnutls_session_t, const char* username,
575 * gnutls_datum_t* salt, gnutls_datum_t *verifier, gnutls_datum_t* g,
576 * gnutls_datum_t* n);
578 * @username contains the actual username.
579 * The @salt, @verifier, @generator and @prime must be filled
580 * in using the gnutls_malloc(). For convenience @prime and @generator
581 * may also be one of the static parameters defined in gnutls.h.
583 * In case the callback returned a negative number then gnutls will
584 * assume that the username does not exist.
586 * In order to prevent attackers from guessing valid usernames,
587 * if a user does not exist, g and n values should be filled in
588 * using a random user's parameters. In that case the callback must
589 * return the special value (1).
591 * The callback function will only be called once per handshake.
592 * The callback function should return 0 on success, while
593 * -1 indicates an error.
595 void
596 gnutls_srp_set_server_credentials_function (gnutls_srp_server_credentials_t
597 cred,
598 gnutls_srp_server_credentials_function
599 * func)
601 cred->pwd_callback = func;
605 * gnutls_srp_set_client_credentials_function:
606 * @cred: is a #gnutls_srp_server_credentials_t structure.
607 * @func: is the callback function
609 * This function can be used to set a callback to retrieve the
610 * username and password for client SRP authentication. The
611 * callback's function form is:
613 * int (*callback)(gnutls_session_t, char** username, char**password);
615 * The @username and @password must be allocated using
616 * gnutls_malloc(). @username and @password should be ASCII strings
617 * or UTF-8 strings prepared using the "SASLprep" profile of
618 * "stringprep".
620 * The callback function will be called once per handshake before the
621 * initial hello message is sent.
623 * The callback should not return a negative error code the second
624 * time called, since the handshake procedure will be aborted.
626 * The callback function should return 0 on success.
627 * -1 indicates an error.
629 void
630 gnutls_srp_set_client_credentials_function (gnutls_srp_client_credentials_t
631 cred,
632 gnutls_srp_client_credentials_function
633 * func)
635 cred->get_function = func;
640 * gnutls_srp_server_get_username:
641 * @session: is a gnutls session
643 * This function will return the username of the peer. This should
644 * only be called in case of SRP authentication and in case of a
645 * server. Returns NULL in case of an error.
647 * Returns: SRP username of the peer, or NULL in case of error.
649 const char *
650 gnutls_srp_server_get_username (gnutls_session_t session)
652 srp_server_auth_info_t info;
654 CHECK_AUTH (GNUTLS_CRD_SRP, NULL);
656 info = _gnutls_get_auth_info (session);
657 if (info == NULL)
658 return NULL;
659 return info->username;
663 * gnutls_srp_verifier:
664 * @username: is the user's name
665 * @password: is the user's password
666 * @salt: should be some randomly generated bytes
667 * @generator: is the generator of the group
668 * @prime: is the group's prime
669 * @res: where the verifier will be stored.
671 * This function will create an SRP verifier, as specified in
672 * RFC2945. The @prime and @generator should be one of the static
673 * parameters defined in gnutls/gnutls.h or may be generated.
675 * The verifier will be allocated with @gnutls_malloc() and will be stored in
676 * @res using binary format.
678 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or an
679 * error code.
682 gnutls_srp_verifier (const char *username, const char *password,
683 const gnutls_datum_t * salt,
684 const gnutls_datum_t * generator,
685 const gnutls_datum_t * prime, gnutls_datum_t * res)
687 bigint_t _n, _g;
688 int ret;
689 size_t digest_size = 20, size;
690 uint8_t digest[20];
692 ret = _gnutls_calc_srp_sha (username, password, salt->data,
693 salt->size, &digest_size, digest);
694 if (ret < 0)
696 gnutls_assert ();
697 return ret;
700 size = prime->size;
701 if (_gnutls_mpi_scan_nz (&_n, prime->data, size))
703 gnutls_assert ();
704 return GNUTLS_E_MPI_SCAN_FAILED;
707 size = generator->size;
708 if (_gnutls_mpi_scan_nz (&_g, generator->data, size))
710 gnutls_assert ();
711 return GNUTLS_E_MPI_SCAN_FAILED;
714 ret = _gnutls_srp_gx (digest, 20, &res->data, _g, _n);
715 if (ret < 0)
717 gnutls_assert ();
718 return ret;
720 res->size = ret;
722 return 0;
726 * gnutls_srp_set_prime_bits:
727 * @session: is a #gnutls_session_t structure.
728 * @bits: is the number of bits
730 * This function sets the minimum accepted number of bits, for use in
731 * an SRP key exchange. If zero, the default 2048 bits will be used.
733 * In the client side it sets the minimum accepted number of bits. If
734 * a server sends a prime with less bits than that
735 * %GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER will be returned by the
736 * handshake.
738 * This function has no effect in server side.
740 * Since: 2.6.0
742 void
743 gnutls_srp_set_prime_bits (gnutls_session_t session, unsigned int bits)
745 session->internals.srp_prime_bits = bits;
748 #endif /* ENABLE_SRP */