Honor uninitialized private key in destructor
[gnutls.git] / lib / gnutls_srp.c
blob6e0785450844deab10cdecdd008476dbd8b6e6f8
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 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;
51 int ret;
53 if (_gnutls_mpi_scan_nz (&x, text, textsize))
55 gnutls_assert ();
56 return GNUTLS_E_MPI_SCAN_FAILED;
59 e = _gnutls_mpi_alloc_like (prime);
60 if (e == NULL)
62 gnutls_assert ();
63 _gnutls_mpi_release (&x);
64 return GNUTLS_E_MEMORY_ERROR;
67 /* e = g^x mod prime (n) */
68 _gnutls_mpi_powm (e, g, x, prime);
69 _gnutls_mpi_release (&x);
71 ret = _gnutls_mpi_print (e, NULL, &result_size);
72 if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
74 *result = galloc_func (result_size);
75 if ((*result) == NULL)
76 return GNUTLS_E_MEMORY_ERROR;
78 _gnutls_mpi_print (e, *result, &result_size);
79 ret = result_size;
81 else
83 gnutls_assert ();
84 ret = GNUTLS_E_MPI_PRINT_FAILED;
87 _gnutls_mpi_release (&e);
89 return ret;
94 /****************
95 * Choose a random value b and calculate B = (k* v + g^b) % N.
96 * where k == SHA1(N|g)
97 * Return: B and if ret_b is not NULL b.
99 bigint_t
100 _gnutls_calc_srp_B (bigint_t * ret_b, bigint_t g, bigint_t n, bigint_t v)
102 bigint_t tmpB = NULL, tmpV = NULL;
103 bigint_t b = NULL, B = NULL, k = NULL;
104 int bits;
107 /* calculate: B = (k*v + g^b) % N
109 bits = _gnutls_mpi_get_nbits (n);
111 tmpV = _gnutls_mpi_alloc_like (n);
113 if (tmpV == NULL)
115 gnutls_assert ();
116 goto error;
119 b = _gnutls_mpi_randomize (NULL, bits, GNUTLS_RND_RANDOM);
121 tmpB = _gnutls_mpi_new (bits);
122 if (tmpB == NULL)
124 gnutls_assert ();
125 goto error;
128 B = _gnutls_mpi_new (bits);
129 if (B == NULL)
131 gnutls_assert ();
132 goto error;
135 k = _gnutls_calc_srp_u (n, g, n);
136 if (k == NULL)
138 gnutls_assert ();
139 goto error;
142 _gnutls_mpi_mulm (tmpV, k, v, n);
143 _gnutls_mpi_powm (tmpB, g, b, n);
145 _gnutls_mpi_addm (B, tmpV, tmpB, n);
147 _gnutls_mpi_release (&k);
148 _gnutls_mpi_release (&tmpB);
149 _gnutls_mpi_release (&tmpV);
151 if (ret_b)
152 *ret_b = b;
153 else
154 _gnutls_mpi_release (&b);
156 return B;
158 error:
159 _gnutls_mpi_release (&b);
160 _gnutls_mpi_release (&B);
161 _gnutls_mpi_release (&k);
162 _gnutls_mpi_release (&tmpB);
163 _gnutls_mpi_release (&tmpV);
164 return NULL;
168 /* This calculates the SHA1(A | B)
169 * A and B will be left-padded with zeros to fill n_size.
171 bigint_t
172 _gnutls_calc_srp_u (bigint_t A, bigint_t B, bigint_t n)
174 size_t b_size, a_size;
175 opaque *holder, hd[MAX_HASH_SIZE];
176 size_t holder_size, hash_size, n_size;
177 digest_hd_st td;
178 int ret;
179 bigint_t res;
181 /* get the size of n in bytes */
182 _gnutls_mpi_print (n, NULL, &n_size);
184 _gnutls_mpi_print (A, NULL, &a_size);
185 _gnutls_mpi_print (B, NULL, &b_size);
187 if (a_size > n_size || b_size > n_size)
189 gnutls_assert ();
190 return NULL; /* internal error */
193 holder_size = n_size + n_size;
195 holder = gnutls_calloc (1, holder_size);
196 if (holder == NULL)
197 return NULL;
199 _gnutls_mpi_print (A, &holder[n_size - a_size], &a_size);
200 _gnutls_mpi_print (B, &holder[n_size + n_size - b_size], &b_size);
202 ret = _gnutls_hash_init (&td, GNUTLS_MAC_SHA1);
203 if (ret < 0)
205 gnutls_free (holder);
206 gnutls_assert ();
207 return NULL;
209 _gnutls_hash (&td, holder, holder_size);
210 _gnutls_hash_deinit (&td, hd);
212 /* convert the bytes of hd to integer
214 hash_size = 20; /* SHA */
215 ret = _gnutls_mpi_scan_nz (&res, hd, hash_size);
216 gnutls_free (holder);
218 if (ret < 0)
220 gnutls_assert ();
221 return NULL;
224 return res;
227 /* S = (A * v^u) ^ b % N
228 * this is our shared key (server premaster secret)
230 bigint_t
231 _gnutls_calc_srp_S1 (bigint_t A, bigint_t b, bigint_t u, bigint_t v,
232 bigint_t n)
234 bigint_t tmp1 = NULL, tmp2 = NULL;
235 bigint_t S = NULL;
237 S = _gnutls_mpi_alloc_like (n);
238 if (S == NULL)
239 return NULL;
241 tmp1 = _gnutls_mpi_alloc_like (n);
242 tmp2 = _gnutls_mpi_alloc_like (n);
244 if (tmp1 == NULL || tmp2 == NULL)
245 goto freeall;
247 _gnutls_mpi_powm (tmp1, v, u, n);
248 _gnutls_mpi_mulm (tmp2, A, tmp1, n);
249 _gnutls_mpi_powm (S, tmp2, b, n);
251 _gnutls_mpi_release (&tmp1);
252 _gnutls_mpi_release (&tmp2);
254 return S;
256 freeall:
257 _gnutls_mpi_release (&tmp1);
258 _gnutls_mpi_release (&tmp2);
259 return NULL;
262 /* A = g^a % N
263 * returns A and a (which is random)
265 bigint_t
266 _gnutls_calc_srp_A (bigint_t * a, bigint_t g, bigint_t n)
268 bigint_t tmpa;
269 bigint_t A;
270 int bits;
272 bits = _gnutls_mpi_get_nbits (n);
273 tmpa = _gnutls_mpi_randomize (NULL, bits, GNUTLS_RND_RANDOM);
275 A = _gnutls_mpi_new (bits);
276 if (A == NULL)
278 gnutls_assert ();
279 _gnutls_mpi_release (&tmpa);
280 return NULL;
282 _gnutls_mpi_powm (A, g, tmpa, n);
284 if (a != NULL)
285 *a = tmpa;
286 else
287 _gnutls_mpi_release (&tmpa);
289 return A;
292 /* generate x = SHA(s | SHA(U | ":" | p))
293 * The output is exactly 20 bytes
295 static int
296 _gnutls_calc_srp_sha (const char *username, const char *password,
297 opaque * salt, int salt_size, size_t * size,
298 void *digest)
300 digest_hd_st td;
301 opaque res[MAX_HASH_SIZE];
302 int ret;
304 *size = 20;
306 ret = _gnutls_hash_init (&td, GNUTLS_MAC_SHA1);
307 if (ret < 0)
309 return GNUTLS_E_MEMORY_ERROR;
311 _gnutls_hash (&td, username, strlen (username));
312 _gnutls_hash (&td, ":", 1);
313 _gnutls_hash (&td, password, strlen (password));
315 _gnutls_hash_deinit (&td, res);
317 ret = _gnutls_hash_init (&td, GNUTLS_MAC_SHA1);
318 if (ret < 0)
320 return GNUTLS_E_MEMORY_ERROR;
323 _gnutls_hash (&td, salt, salt_size);
324 _gnutls_hash (&td, res, 20); /* 20 bytes is the output of sha1 */
326 _gnutls_hash_deinit (&td, digest);
328 return 0;
332 _gnutls_calc_srp_x (char *username, char *password, opaque * salt,
333 size_t salt_size, size_t * size, void *digest)
336 return _gnutls_calc_srp_sha (username, password, salt,
337 salt_size, size, digest);
341 /* S = (B - k*g^x) ^ (a + u * x) % N
342 * this is our shared key (client premaster secret)
344 bigint_t
345 _gnutls_calc_srp_S2 (bigint_t B, bigint_t g, bigint_t x, bigint_t a,
346 bigint_t u, bigint_t n)
348 bigint_t S = NULL, tmp1 = NULL, tmp2 = NULL;
349 bigint_t tmp4 = NULL, tmp3 = NULL, k = NULL;
351 S = _gnutls_mpi_alloc_like (n);
352 if (S == NULL)
353 return NULL;
355 tmp1 = _gnutls_mpi_alloc_like (n);
356 tmp2 = _gnutls_mpi_alloc_like (n);
357 tmp3 = _gnutls_mpi_alloc_like (n);
358 if (tmp1 == NULL || tmp2 == NULL || tmp3 == NULL)
360 goto freeall;
363 k = _gnutls_calc_srp_u (n, g, n);
364 if (k == NULL)
366 gnutls_assert ();
367 goto freeall;
370 _gnutls_mpi_powm (tmp1, g, x, n); /* g^x */
371 _gnutls_mpi_mulm (tmp3, tmp1, k, n); /* k*g^x mod n */
372 _gnutls_mpi_subm (tmp2, B, tmp3, n);
374 tmp4 = _gnutls_mpi_alloc_like (n);
375 if (tmp4 == NULL)
376 goto freeall;
378 _gnutls_mpi_mul (tmp1, u, x);
379 _gnutls_mpi_add (tmp4, a, tmp1);
380 _gnutls_mpi_powm (S, tmp2, tmp4, n);
382 _gnutls_mpi_release (&tmp1);
383 _gnutls_mpi_release (&tmp2);
384 _gnutls_mpi_release (&tmp3);
385 _gnutls_mpi_release (&tmp4);
386 _gnutls_mpi_release (&k);
388 return S;
390 freeall:
391 _gnutls_mpi_release (&k);
392 _gnutls_mpi_release (&tmp1);
393 _gnutls_mpi_release (&tmp2);
394 _gnutls_mpi_release (&tmp3);
395 _gnutls_mpi_release (&tmp4);
396 _gnutls_mpi_release (&S);
397 return NULL;
401 * gnutls_srp_free_client_credentials:
402 * @sc: is a #gnutls_srp_client_credentials_t structure.
404 * This structure is complex enough to manipulate directly thus
405 * this helper function is provided in order to free (deallocate) it.
407 void
408 gnutls_srp_free_client_credentials (gnutls_srp_client_credentials_t sc)
410 gnutls_free (sc->username);
411 gnutls_free (sc->password);
412 gnutls_free (sc);
416 * gnutls_srp_allocate_client_credentials:
417 * @sc: is a pointer to a #gnutls_srp_server_credentials_t structure.
419 * This structure is complex enough to manipulate directly thus
420 * this helper function is provided in order to allocate it.
422 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or an
423 * error code.
426 gnutls_srp_allocate_client_credentials (gnutls_srp_client_credentials_t * sc)
428 *sc = gnutls_calloc (1, sizeof (srp_client_credentials_st));
430 if (*sc == NULL)
431 return GNUTLS_E_MEMORY_ERROR;
433 return 0;
437 * gnutls_srp_set_client_credentials:
438 * @res: is a #gnutls_srp_client_credentials_t structure.
439 * @username: is the user's userid
440 * @password: is the user's password
442 * This function sets the username and password, in a
443 * #gnutls_srp_client_credentials_t structure. Those will be used in
444 * SRP authentication. @username and @password should be ASCII
445 * strings or UTF-8 strings prepared using the "SASLprep" profile of
446 * "stringprep".
448 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or an
449 * error code.
452 gnutls_srp_set_client_credentials (gnutls_srp_client_credentials_t res,
453 const char *username, const char *password)
456 if (username == NULL || password == NULL)
458 gnutls_assert ();
459 return GNUTLS_E_INVALID_REQUEST;
462 res->username = gnutls_strdup (username);
463 if (res->username == NULL)
464 return GNUTLS_E_MEMORY_ERROR;
466 res->password = gnutls_strdup (password);
467 if (res->password == NULL)
469 gnutls_free (res->username);
470 return GNUTLS_E_MEMORY_ERROR;
473 return 0;
477 * gnutls_srp_free_server_credentials:
478 * @sc: is a #gnutls_srp_server_credentials_t structure.
480 * This structure is complex enough to manipulate directly thus
481 * this helper function is provided in order to free (deallocate) it.
483 void
484 gnutls_srp_free_server_credentials (gnutls_srp_server_credentials_t sc)
486 gnutls_free (sc->password_file);
487 gnutls_free (sc->password_conf_file);
489 gnutls_free (sc);
493 * gnutls_srp_allocate_server_credentials:
494 * @sc: is a pointer to a #gnutls_srp_server_credentials_t structure.
496 * This structure is complex enough to manipulate directly thus this
497 * helper function is provided in order to allocate it.
499 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or an
500 * error code.
503 gnutls_srp_allocate_server_credentials (gnutls_srp_server_credentials_t * sc)
505 *sc = gnutls_calloc (1, sizeof (srp_server_cred_st));
507 if (*sc == NULL)
508 return GNUTLS_E_MEMORY_ERROR;
510 return 0;
514 * gnutls_srp_set_server_credentials_file:
515 * @res: is a #gnutls_srp_server_credentials_t structure.
516 * @password_file: is the SRP password file (tpasswd)
517 * @password_conf_file: is the SRP password conf file (tpasswd.conf)
519 * This function sets the password files, in a
520 * #gnutls_srp_server_credentials_t structure. Those password files
521 * hold usernames and verifiers and will be used for SRP
522 * authentication.
524 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or an
525 * error code.
528 gnutls_srp_set_server_credentials_file (gnutls_srp_server_credentials_t res,
529 const char *password_file,
530 const char *password_conf_file)
533 if (password_file == NULL || password_conf_file == NULL)
535 gnutls_assert ();
536 return GNUTLS_E_INVALID_REQUEST;
539 /* Check if the files can be opened */
540 if (_gnutls_file_exists (password_file) != 0)
542 gnutls_assert ();
543 return GNUTLS_E_FILE_ERROR;
546 if (_gnutls_file_exists (password_conf_file) != 0)
548 gnutls_assert ();
549 return GNUTLS_E_FILE_ERROR;
552 res->password_file = gnutls_strdup (password_file);
553 if (res->password_file == NULL)
555 gnutls_assert ();
556 return GNUTLS_E_MEMORY_ERROR;
559 res->password_conf_file = gnutls_strdup (password_conf_file);
560 if (res->password_conf_file == NULL)
562 gnutls_assert ();
563 gnutls_free (res->password_file);
564 res->password_file = NULL;
565 return GNUTLS_E_MEMORY_ERROR;
568 return 0;
573 * gnutls_srp_set_server_credentials_function:
574 * @cred: is a #gnutls_srp_server_credentials_t structure.
575 * @func: is the callback function
577 * This function can be used to set a callback to retrieve the user's
578 * SRP credentials. The callback's function form is:
580 * int (*callback)(gnutls_session_t, const char* username,
581 * gnutls_datum_t* salt, gnutls_datum_t *verifier, gnutls_datum_t* g,
582 * gnutls_datum_t* n);
584 * @username contains the actual username.
585 * The @salt, @verifier, @generator and @prime must be filled
586 * in using the gnutls_malloc(). For convenience @prime and @generator
587 * may also be one of the static parameters defined in extra.h.
589 * In case the callback returned a negative number then gnutls will
590 * assume that the username does not exist.
592 * In order to prevent attackers from guessing valid usernames,
593 * if a user does not exist, g and n values should be filled in
594 * using a random user's parameters. In that case the callback must
595 * return the special value (1).
597 * The callback function will only be called once per handshake.
598 * The callback function should return 0 on success, while
599 * -1 indicates an error.
601 void
602 gnutls_srp_set_server_credentials_function (gnutls_srp_server_credentials_t
603 cred,
604 gnutls_srp_server_credentials_function
605 * func)
607 cred->pwd_callback = func;
611 * gnutls_srp_set_client_credentials_function:
612 * @cred: is a #gnutls_srp_server_credentials_t structure.
613 * @func: is the callback function
615 * This function can be used to set a callback to retrieve the
616 * username and password for client SRP authentication. The
617 * callback's function form is:
619 * int (*callback)(gnutls_session_t, char** username, char**password);
621 * The @username and @password must be allocated using
622 * gnutls_malloc(). @username and @password should be ASCII strings
623 * or UTF-8 strings prepared using the "SASLprep" profile of
624 * "stringprep".
626 * The callback function will be called once per handshake before the
627 * initial hello message is sent.
629 * The callback should not return a negative error code the second
630 * time called, since the handshake procedure will be aborted.
632 * The callback function should return 0 on success.
633 * -1 indicates an error.
635 void
636 gnutls_srp_set_client_credentials_function (gnutls_srp_client_credentials_t
637 cred,
638 gnutls_srp_client_credentials_function
639 * func)
641 cred->get_function = func;
646 * gnutls_srp_server_get_username:
647 * @session: is a gnutls session
649 * This function will return the username of the peer. This should
650 * only be called in case of SRP authentication and in case of a
651 * server. Returns NULL in case of an error.
653 * Returns: SRP username of the peer, or NULL in case of error.
655 const char *
656 gnutls_srp_server_get_username (gnutls_session_t session)
658 srp_server_auth_info_t info;
660 CHECK_AUTH (GNUTLS_CRD_SRP, NULL);
662 info = _gnutls_get_auth_info (session);
663 if (info == NULL)
664 return NULL;
665 return info->username;
669 * gnutls_srp_verifier:
670 * @username: is the user's name
671 * @password: is the user's password
672 * @salt: should be some randomly generated bytes
673 * @generator: is the generator of the group
674 * @prime: is the group's prime
675 * @res: where the verifier will be stored.
677 * This function will create an SRP verifier, as specified in
678 * RFC2945. The @prime and @generator should be one of the static
679 * parameters defined in gnutls/extra.h or may be generated using the
680 * libgcrypt functions gcry_prime_generate() and
681 * gcry_prime_group_generator().
683 * The verifier will be allocated with @malloc and will be stored in
684 * @res using binary format.
686 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or an
687 * error code.
690 gnutls_srp_verifier (const char *username, const char *password,
691 const gnutls_datum_t * salt,
692 const gnutls_datum_t * generator,
693 const gnutls_datum_t * prime, gnutls_datum_t * res)
695 bigint_t _n, _g;
696 int ret;
697 size_t digest_size = 20, size;
698 opaque digest[20];
700 ret = _gnutls_calc_srp_sha (username, password, salt->data,
701 salt->size, &digest_size, digest);
702 if (ret < 0)
704 gnutls_assert ();
705 return ret;
708 size = prime->size;
709 if (_gnutls_mpi_scan_nz (&_n, prime->data, size))
711 gnutls_assert ();
712 return GNUTLS_E_MPI_SCAN_FAILED;
715 size = generator->size;
716 if (_gnutls_mpi_scan_nz (&_g, generator->data, size))
718 gnutls_assert ();
719 return GNUTLS_E_MPI_SCAN_FAILED;
722 ret = _gnutls_srp_gx (digest, 20, &res->data, _g, _n, malloc);
723 if (ret < 0)
725 gnutls_assert ();
726 return ret;
728 res->size = ret;
730 return 0;
734 * gnutls_srp_set_prime_bits:
735 * @session: is a #gnutls_session_t structure.
736 * @bits: is the number of bits
738 * This function sets the minimum accepted number of bits, for use in
739 * an SRP key exchange. If zero, the default 2048 bits will be used.
741 * In the client side it sets the minimum accepted number of bits. If
742 * a server sends a prime with less bits than that
743 * %GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER will be returned by the
744 * handshake.
746 * This function has no effect in server side.
748 * Since: 2.6.0
750 void
751 gnutls_srp_set_prime_bits (gnutls_session_t session, unsigned int bits)
753 session->internals.srp_prime_bits = bits;
756 #endif /* ENABLE_SRP */