Use libtasn1 v2.4.
[gnutls.git] / lib / gnutls_srp.c
blobaababc41ba4f40165dd82fc737d925608fc2d969
1 /*
2 * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2008, 2009, 2010 Free
3 * Software Foundation, Inc.
5 * Author: Nikos Mavrogiannopoulos
7 * This file is part of GNUTLS.
9 * The GNUTLS library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1 of
12 * the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
22 * USA
26 #include <gnutls_int.h>
27 #include <gnutls_errors.h>
28 #include <auth_srp.h>
29 #include <gnutls_state.h>
31 #ifdef ENABLE_SRP
33 #include <gnutls_srp.h>
34 #include <auth_srp_passwd.h>
35 #include <gnutls_mpi.h>
36 #include <gnutls_num.h>
37 #include <gnutls_helper.h>
39 #include "debug.h"
42 /* Here functions for SRP (like g^x mod n) are defined
45 int
46 _gnutls_srp_gx (opaque * text, size_t textsize, opaque ** result,
47 bigint_t g, bigint_t prime, gnutls_alloc_function galloc_func)
49 bigint_t x, e;
50 size_t result_size;
52 if (_gnutls_mpi_scan_nz (&x, text, textsize))
54 gnutls_assert ();
55 return GNUTLS_E_MPI_SCAN_FAILED;
58 e = _gnutls_mpi_alloc_like (prime);
59 if (e == NULL)
61 gnutls_assert ();
62 _gnutls_mpi_release (&x);
63 return GNUTLS_E_MEMORY_ERROR;
66 /* e = g^x mod prime (n) */
67 _gnutls_mpi_powm (e, g, x, prime);
68 _gnutls_mpi_release (&x);
70 _gnutls_mpi_print (e, NULL, &result_size);
71 if (result != NULL)
73 *result = galloc_func (result_size);
74 if ((*result) == NULL)
75 return GNUTLS_E_MEMORY_ERROR;
77 _gnutls_mpi_print (e, *result, &result_size);
80 _gnutls_mpi_release (&e);
82 return result_size;
87 /****************
88 * Choose a random value b and calculate B = (k* v + g^b) % N.
89 * where k == SHA1(N|g)
90 * Return: B and if ret_b is not NULL b.
92 bigint_t
93 _gnutls_calc_srp_B (bigint_t * ret_b, bigint_t g, bigint_t n, bigint_t v)
95 bigint_t tmpB = NULL, tmpV = NULL;
96 bigint_t b = NULL, B = NULL, k = NULL;
97 int bits;
100 /* calculate: B = (k*v + g^b) % N
102 bits = _gnutls_mpi_get_nbits (n);
104 tmpV = _gnutls_mpi_alloc_like (n);
106 if (tmpV == NULL)
108 gnutls_assert ();
109 goto error;
112 b = _gnutls_mpi_randomize (NULL, bits, GNUTLS_RND_RANDOM);
114 tmpB = _gnutls_mpi_new (bits);
115 if (tmpB == NULL)
117 gnutls_assert ();
118 goto error;
121 B = _gnutls_mpi_new (bits);
122 if (B == NULL)
124 gnutls_assert ();
125 goto error;
128 k = _gnutls_calc_srp_u (n, g, n);
129 if (k == NULL)
131 gnutls_assert ();
132 goto error;
135 _gnutls_mpi_mulm (tmpV, k, v, n);
136 _gnutls_mpi_powm (tmpB, g, b, n);
138 _gnutls_mpi_addm (B, tmpV, tmpB, n);
140 _gnutls_mpi_release (&k);
141 _gnutls_mpi_release (&tmpB);
142 _gnutls_mpi_release (&tmpV);
144 if (ret_b)
145 *ret_b = b;
146 else
147 _gnutls_mpi_release (&b);
149 return B;
151 error:
152 _gnutls_mpi_release (&b);
153 _gnutls_mpi_release (&B);
154 _gnutls_mpi_release (&k);
155 _gnutls_mpi_release (&tmpB);
156 _gnutls_mpi_release (&tmpV);
157 return NULL;
161 /* This calculates the SHA1(A | B)
162 * A and B will be left-padded with zeros to fill n_size.
164 bigint_t
165 _gnutls_calc_srp_u (bigint_t A, bigint_t B, bigint_t n)
167 size_t b_size, a_size;
168 opaque *holder, hd[MAX_HASH_SIZE];
169 size_t holder_size, hash_size, n_size;
170 digest_hd_st td;
171 int ret;
172 bigint_t res;
174 /* get the size of n in bytes */
175 _gnutls_mpi_print (n, NULL, &n_size);
177 _gnutls_mpi_print (A, NULL, &a_size);
178 _gnutls_mpi_print (B, NULL, &b_size);
180 if (a_size > n_size || b_size > n_size)
182 gnutls_assert ();
183 return NULL; /* internal error */
186 holder_size = n_size + n_size;
188 holder = gnutls_calloc (1, holder_size);
189 if (holder == NULL)
190 return NULL;
192 _gnutls_mpi_print (A, &holder[n_size - a_size], &a_size);
193 _gnutls_mpi_print (B, &holder[n_size + n_size - b_size], &b_size);
195 ret = _gnutls_hash_init (&td, GNUTLS_MAC_SHA1);
196 if (ret < 0)
198 gnutls_free (holder);
199 gnutls_assert ();
200 return NULL;
202 _gnutls_hash (&td, holder, holder_size);
203 _gnutls_hash_deinit (&td, hd);
205 /* convert the bytes of hd to integer
207 hash_size = 20; /* SHA */
208 ret = _gnutls_mpi_scan_nz (&res, hd, hash_size);
209 gnutls_free (holder);
211 if (ret < 0)
213 gnutls_assert ();
214 return NULL;
217 return res;
220 /* S = (A * v^u) ^ b % N
221 * this is our shared key (server premaster secret)
223 bigint_t
224 _gnutls_calc_srp_S1 (bigint_t A, bigint_t b, bigint_t u, bigint_t v,
225 bigint_t n)
227 bigint_t tmp1 = NULL, tmp2 = NULL;
228 bigint_t S = NULL;
230 S = _gnutls_mpi_alloc_like (n);
231 if (S == NULL)
232 return NULL;
234 tmp1 = _gnutls_mpi_alloc_like (n);
235 tmp2 = _gnutls_mpi_alloc_like (n);
237 if (tmp1 == NULL || tmp2 == NULL)
238 goto freeall;
240 _gnutls_mpi_powm (tmp1, v, u, n);
241 _gnutls_mpi_mulm (tmp2, A, tmp1, n);
242 _gnutls_mpi_powm (S, tmp2, b, n);
244 _gnutls_mpi_release (&tmp1);
245 _gnutls_mpi_release (&tmp2);
247 return S;
249 freeall:
250 _gnutls_mpi_release (&tmp1);
251 _gnutls_mpi_release (&tmp2);
252 return NULL;
255 /* A = g^a % N
256 * returns A and a (which is random)
258 bigint_t
259 _gnutls_calc_srp_A (bigint_t * a, bigint_t g, bigint_t n)
261 bigint_t tmpa;
262 bigint_t A;
263 int bits;
265 bits = _gnutls_mpi_get_nbits (n);
266 tmpa = _gnutls_mpi_randomize (NULL, bits, GNUTLS_RND_RANDOM);
268 A = _gnutls_mpi_new (bits);
269 if (A == NULL)
271 gnutls_assert ();
272 _gnutls_mpi_release (&tmpa);
273 return NULL;
275 _gnutls_mpi_powm (A, g, tmpa, n);
277 if (a != NULL)
278 *a = tmpa;
279 else
280 _gnutls_mpi_release (&tmpa);
282 return A;
285 /* generate x = SHA(s | SHA(U | ":" | p))
286 * The output is exactly 20 bytes
288 static int
289 _gnutls_calc_srp_sha (const char *username, const char *password,
290 opaque * salt, int salt_size, size_t * size,
291 void *digest)
293 digest_hd_st td;
294 opaque res[MAX_HASH_SIZE];
295 int ret;
297 *size = 20;
299 ret = _gnutls_hash_init (&td, GNUTLS_MAC_SHA1);
300 if (ret < 0)
302 return GNUTLS_E_MEMORY_ERROR;
304 _gnutls_hash (&td, username, strlen (username));
305 _gnutls_hash (&td, ":", 1);
306 _gnutls_hash (&td, password, strlen (password));
308 _gnutls_hash_deinit (&td, res);
310 ret = _gnutls_hash_init (&td, GNUTLS_MAC_SHA1);
311 if (ret < 0)
313 return GNUTLS_E_MEMORY_ERROR;
316 _gnutls_hash (&td, salt, salt_size);
317 _gnutls_hash (&td, res, 20); /* 20 bytes is the output of sha1 */
319 _gnutls_hash_deinit (&td, digest);
321 return 0;
325 _gnutls_calc_srp_x (char *username, char *password, opaque * salt,
326 size_t salt_size, size_t * size, void *digest)
329 return _gnutls_calc_srp_sha (username, password, salt,
330 salt_size, size, digest);
334 /* S = (B - k*g^x) ^ (a + u * x) % N
335 * this is our shared key (client premaster secret)
337 bigint_t
338 _gnutls_calc_srp_S2 (bigint_t B, bigint_t g, bigint_t x, bigint_t a,
339 bigint_t u, bigint_t n)
341 bigint_t S = NULL, tmp1 = NULL, tmp2 = NULL;
342 bigint_t tmp4 = NULL, tmp3 = NULL, k = NULL;
344 S = _gnutls_mpi_alloc_like (n);
345 if (S == NULL)
346 return NULL;
348 tmp1 = _gnutls_mpi_alloc_like (n);
349 tmp2 = _gnutls_mpi_alloc_like (n);
350 tmp3 = _gnutls_mpi_alloc_like (n);
351 if (tmp1 == NULL || tmp2 == NULL || tmp3 == NULL)
353 goto freeall;
356 k = _gnutls_calc_srp_u (n, g, n);
357 if (k == NULL)
359 gnutls_assert ();
360 goto freeall;
363 _gnutls_mpi_powm (tmp1, g, x, n); /* g^x */
364 _gnutls_mpi_mulm (tmp3, tmp1, k, n); /* k*g^x mod n */
365 _gnutls_mpi_subm (tmp2, B, tmp3, n);
367 tmp4 = _gnutls_mpi_alloc_like (n);
368 if (tmp4 == NULL)
369 goto freeall;
371 _gnutls_mpi_mul (tmp1, u, x);
372 _gnutls_mpi_add (tmp4, a, tmp1);
373 _gnutls_mpi_powm (S, tmp2, tmp4, n);
375 _gnutls_mpi_release (&tmp1);
376 _gnutls_mpi_release (&tmp2);
377 _gnutls_mpi_release (&tmp3);
378 _gnutls_mpi_release (&tmp4);
379 _gnutls_mpi_release (&k);
381 return S;
383 freeall:
384 _gnutls_mpi_release (&k);
385 _gnutls_mpi_release (&tmp1);
386 _gnutls_mpi_release (&tmp2);
387 _gnutls_mpi_release (&tmp3);
388 _gnutls_mpi_release (&tmp4);
389 _gnutls_mpi_release (&S);
390 return NULL;
394 * gnutls_srp_free_client_credentials - Used to free an allocated gnutls_srp_client_credentials_t structure
395 * @sc: is a #gnutls_srp_client_credentials_t structure.
397 * This structure is complex enough to manipulate directly thus
398 * 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 - Used to allocate an gnutls_srp_server_credentials_t structure
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 - Used to set the username/password, in a gnutls_srp_client_credentials_t structure
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 - Used to free an allocated gnutls_srp_server_credentials_t structure
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.
478 void
479 gnutls_srp_free_server_credentials (gnutls_srp_server_credentials_t sc)
481 gnutls_free (sc->password_file);
482 gnutls_free (sc->password_conf_file);
484 gnutls_free (sc);
488 * gnutls_srp_allocate_server_credentials - Used to allocate an gnutls_srp_server_credentials_t structure
489 * @sc: is a pointer to a #gnutls_srp_server_credentials_t structure.
491 * This structure is complex enough to manipulate directly thus this
492 * helper function is provided in order to allocate it.
494 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or an
495 * error code.
498 gnutls_srp_allocate_server_credentials (gnutls_srp_server_credentials_t * sc)
500 *sc = gnutls_calloc (1, sizeof (srp_server_cred_st));
502 if (*sc == NULL)
503 return GNUTLS_E_MEMORY_ERROR;
505 return 0;
509 * gnutls_srp_set_server_credentials_file - Used to set the password files, in a gnutls_srp_server_credentials_t structure
510 * @res: is a #gnutls_srp_server_credentials_t structure.
511 * @password_file: is the SRP password file (tpasswd)
512 * @password_conf_file: is the SRP password conf file (tpasswd.conf)
514 * This function sets the password files, in a
515 * #gnutls_srp_server_credentials_t structure. Those password files
516 * hold usernames and verifiers and will be used for SRP
517 * authentication.
519 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or an
520 * error code.
523 gnutls_srp_set_server_credentials_file (gnutls_srp_server_credentials_t res,
524 const char *password_file,
525 const char *password_conf_file)
528 if (password_file == NULL || password_conf_file == NULL)
530 gnutls_assert ();
531 return GNUTLS_E_INVALID_REQUEST;
534 /* Check if the files can be opened */
535 if (_gnutls_file_exists (password_file) != 0)
537 gnutls_assert ();
538 return GNUTLS_E_FILE_ERROR;
541 if (_gnutls_file_exists (password_conf_file) != 0)
543 gnutls_assert ();
544 return GNUTLS_E_FILE_ERROR;
547 res->password_file = gnutls_strdup (password_file);
548 if (res->password_file == NULL)
550 gnutls_assert ();
551 return GNUTLS_E_MEMORY_ERROR;
554 res->password_conf_file = gnutls_strdup (password_conf_file);
555 if (res->password_conf_file == NULL)
557 gnutls_assert ();
558 gnutls_free (res->password_file);
559 res->password_file = NULL;
560 return GNUTLS_E_MEMORY_ERROR;
563 return 0;
568 * gnutls_srp_set_server_credentials_function - Used to set a callback to retrieve the user's SRP credentials
569 * @cred: is a #gnutls_srp_server_credentials_t structure.
570 * @func: is the callback function
572 * This function can be used to set a callback to retrieve the user's SRP credentials.
573 * 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 extra.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.
596 void
597 gnutls_srp_set_server_credentials_function (gnutls_srp_server_credentials_t
598 cred,
599 gnutls_srp_server_credentials_function
600 * func)
602 cred->pwd_callback = func;
606 * gnutls_srp_set_client_credentials_function - Used to set a callback to retrieve the username and password
607 * @cred: is a #gnutls_srp_server_credentials_t structure.
608 * @func: is the callback function
610 * This function can be used to set a callback to retrieve the username and
611 * password for client SRP authentication.
613 * The callback's function form is:
615 * int (*callback)(gnutls_session_t, char** username, char**password);
617 * The @username and @password must be allocated using
618 * gnutls_malloc(). @username and @password should be ASCII strings
619 * or UTF-8 strings prepared using the "SASLprep" profile of
620 * "stringprep".
622 * The callback function will be called once per handshake before the
623 * initial hello message is sent.
625 * The callback should not return a negative error code the second
626 * time called, since the handshake procedure will be aborted.
628 * The callback function should return 0 on success.
629 * -1 indicates an error.
631 void
632 gnutls_srp_set_client_credentials_function (gnutls_srp_client_credentials_t
633 cred,
634 gnutls_srp_client_credentials_function
635 * func)
637 cred->get_function = func;
642 * gnutls_srp_server_get_username - return the username of the peer
643 * @session: is a gnutls session
645 * This function will return the username of the peer. This should
646 * only be called in case of SRP authentication and in case of a
647 * server. Returns NULL in case of an error.
649 * Returns: SRP username of the peer, or NULL in case of error.
651 const char *
652 gnutls_srp_server_get_username (gnutls_session_t session)
654 srp_server_auth_info_t info;
656 CHECK_AUTH (GNUTLS_CRD_SRP, NULL);
658 info = _gnutls_get_auth_info (session);
659 if (info == NULL)
660 return NULL;
661 return info->username;
665 * gnutls_srp_verifier - Used to calculate an SRP verifier
666 * @username: is the user's name
667 * @password: is the user's password
668 * @salt: should be some randomly generated bytes
669 * @generator: is the generator of the group
670 * @prime: is the group's prime
671 * @res: where the verifier will be stored.
673 * This function will create an SRP verifier, as specified in
674 * RFC2945. The @prime and @generator should be one of the static
675 * parameters defined in gnutls/extra.h or may be generated using the
676 * libgcrypt functions gcry_prime_generate() and
677 * gcry_prime_group_generator().
679 * The verifier will be allocated with @malloc and will be stored in
680 * @res using binary format.
682 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or an
683 * error code.
686 gnutls_srp_verifier (const char *username, const char *password,
687 const gnutls_datum_t * salt,
688 const gnutls_datum_t * generator,
689 const gnutls_datum_t * prime, gnutls_datum_t * res)
691 bigint_t _n, _g;
692 int ret;
693 size_t digest_size = 20, size;
694 opaque digest[20];
696 ret = _gnutls_calc_srp_sha (username, password, salt->data,
697 salt->size, &digest_size, digest);
698 if (ret < 0)
700 gnutls_assert ();
701 return ret;
704 size = prime->size;
705 if (_gnutls_mpi_scan_nz (&_n, prime->data, size))
707 gnutls_assert ();
708 return GNUTLS_E_MPI_SCAN_FAILED;
711 size = generator->size;
712 if (_gnutls_mpi_scan_nz (&_g, generator->data, size))
714 gnutls_assert ();
715 return GNUTLS_E_MPI_SCAN_FAILED;
718 ret = _gnutls_srp_gx (digest, 20, &res->data, _g, _n, malloc);
719 if (ret < 0)
721 gnutls_assert ();
722 return ret;
724 res->size = ret;
726 return 0;
730 * gnutls_srp_set_prime_bits - set the minimum bits for a SRP ciphersuite
731 * @session: is a #gnutls_session_t structure.
732 * @bits: is the number of bits
734 * This function sets the minimum accepted number of bits, for use in
735 * an SRP key exchange. If zero, the default 2048 bits will be used.
737 * In the client side it sets the minimum accepted number of bits. If
738 * a server sends a prime with less bits than that
739 * %GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER will be returned by the
740 * handshake.
742 * This function has no effect in server side.
744 * Since: 2.6.0
746 void
747 gnutls_srp_set_prime_bits (gnutls_session_t session, unsigned int bits)
749 session->internals.srp_prime_bits = bits;
752 #endif /* ENABLE_SRP */