2 * Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation
4 * Author: Nikos Mavroyanopoulos
6 * This file is part of GNUTLS.
8 * The GNUTLS library 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.
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
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
25 #include <gnutls_int.h>
26 #include <gnutls_errors.h>
28 #include <gnutls_state.h>
32 #include <gnutls_srp.h>
33 #include <auth_srp_passwd.h>
34 #include <gnutls_mpi.h>
35 #include <gnutls_num.h>
36 #include <gnutls_helper.h>
41 /* Here functions for SRP (like g^x mod n) are defined
45 _gnutls_srp_gx (opaque
* text
, size_t textsize
, opaque
** result
,
46 mpi_t g
, mpi_t prime
, gnutls_alloc_function galloc_func
)
51 if (_gnutls_mpi_scan_nz (&x
, text
, &textsize
))
54 return GNUTLS_E_MPI_SCAN_FAILED
;
57 e
= _gnutls_mpi_alloc_like (prime
);
61 _gnutls_mpi_release (&x
);
62 return GNUTLS_E_MEMORY_ERROR
;
65 /* e = g^x mod prime (n) */
66 _gnutls_mpi_powm (e
, g
, x
, prime
);
67 _gnutls_mpi_release (&x
);
69 _gnutls_mpi_print (NULL
, &result_size
, e
);
72 *result
= galloc_func (result_size
);
73 if ((*result
) == NULL
)
74 return GNUTLS_E_MEMORY_ERROR
;
76 _gnutls_mpi_print (*result
, &result_size
, e
);
79 _gnutls_mpi_release (&e
);
87 * Choose a random value b and calculate B = (k* v + g^b) % N.
88 * where k == SHA1(N|g)
89 * Return: B and if ret_b is not NULL b.
92 _gnutls_calc_srp_B (mpi_t
* ret_b
, mpi_t g
, mpi_t n
, mpi_t v
)
94 mpi_t tmpB
= NULL
, tmpV
= NULL
;
95 mpi_t b
= NULL
, B
= NULL
, k
= NULL
;
99 /* calculate: B = (k*v + g^b) % N
101 bits
= _gnutls_mpi_get_nbits (n
);
102 b
= _gnutls_mpi_snew (bits
);
109 tmpV
= _gnutls_mpi_alloc_like (n
);
117 _gnutls_mpi_randomize (b
, bits
, GCRY_STRONG_RANDOM
);
119 tmpB
= _gnutls_mpi_snew (bits
);
126 B
= _gnutls_mpi_snew (bits
);
133 k
= _gnutls_calc_srp_u (n
, g
, n
);
140 _gnutls_mpi_mulm (tmpV
, k
, v
, n
);
141 _gnutls_mpi_powm (tmpB
, g
, b
, n
);
143 _gnutls_mpi_addm (B
, tmpV
, tmpB
, n
);
145 _gnutls_mpi_release (&k
);
146 _gnutls_mpi_release (&tmpB
);
147 _gnutls_mpi_release (&tmpV
);
152 _gnutls_mpi_release (&b
);
157 _gnutls_mpi_release (&b
);
158 _gnutls_mpi_release (&B
);
159 _gnutls_mpi_release (&k
);
160 _gnutls_mpi_release (&tmpB
);
161 _gnutls_mpi_release (&tmpV
);
166 /* This calculates the SHA1(A | B)
167 * A and B will be left-padded with zeros to fill n_size.
170 _gnutls_calc_srp_u (mpi_t A
, mpi_t B
, mpi_t n
)
172 size_t b_size
, a_size
;
173 opaque
*holder
, hd
[MAX_HASH_SIZE
];
174 size_t holder_size
, hash_size
, n_size
;
175 GNUTLS_HASH_HANDLE td
;
179 /* get the size of n in bytes */
180 _gnutls_mpi_print (NULL
, &n_size
, n
);
182 _gnutls_mpi_print (NULL
, &a_size
, A
);
183 _gnutls_mpi_print (NULL
, &b_size
, B
);
185 if (a_size
> n_size
|| b_size
> n_size
)
188 return NULL
; /* internal error */
191 holder_size
= n_size
+ n_size
;
193 holder
= gnutls_calloc (1, holder_size
);
197 _gnutls_mpi_print (&holder
[n_size
- a_size
], &a_size
, A
);
198 _gnutls_mpi_print (&holder
[n_size
+ n_size
- b_size
], &b_size
, B
);
200 td
= _gnutls_hash_init (GNUTLS_MAC_SHA1
);
203 gnutls_free (holder
);
207 _gnutls_hash (td
, holder
, holder_size
);
208 _gnutls_hash_deinit (td
, hd
);
210 /* convert the bytes of hd to integer
212 hash_size
= 20; /* SHA */
213 ret
= _gnutls_mpi_scan_nz (&res
, hd
, &hash_size
);
214 gnutls_free (holder
);
225 /* S = (A * v^u) ^ b % N
226 * this is our shared key (server premaster secret)
229 _gnutls_calc_srp_S1 (mpi_t A
, mpi_t b
, mpi_t u
, mpi_t v
, mpi_t n
)
231 mpi_t tmp1
= NULL
, tmp2
= NULL
;
234 S
= _gnutls_mpi_alloc_like (n
);
238 tmp1
= _gnutls_mpi_alloc_like (n
);
239 tmp2
= _gnutls_mpi_alloc_like (n
);
241 if (tmp1
== NULL
|| tmp2
== NULL
)
244 _gnutls_mpi_powm (tmp1
, v
, u
, n
);
245 _gnutls_mpi_mulm (tmp2
, A
, tmp1
, n
);
246 _gnutls_mpi_powm (S
, tmp2
, b
, n
);
248 _gnutls_mpi_release (&tmp1
);
249 _gnutls_mpi_release (&tmp2
);
254 _gnutls_mpi_release (&tmp1
);
255 _gnutls_mpi_release (&tmp2
);
260 * returns A and a (which is random)
263 _gnutls_calc_srp_A (mpi_t
* a
, mpi_t g
, mpi_t n
)
269 bits
= _gnutls_mpi_get_nbits (n
);
270 tmpa
= _gnutls_mpi_snew (bits
);
277 _gnutls_mpi_randomize (tmpa
, bits
, GCRY_STRONG_RANDOM
);
279 A
= _gnutls_mpi_snew (bits
);
283 _gnutls_mpi_release (&tmpa
);
286 _gnutls_mpi_powm (A
, g
, tmpa
, n
);
291 _gnutls_mpi_release (&tmpa
);
296 /* generate x = SHA(s | SHA(U | ":" | p))
297 * The output is exactly 20 bytes
300 _gnutls_calc_srp_sha (const char *username
, const char *password
,
301 opaque
* salt
, int salt_size
, size_t * size
,
304 GNUTLS_HASH_HANDLE td
;
305 opaque res
[MAX_HASH_SIZE
];
309 td
= _gnutls_hash_init (GNUTLS_MAC_SHA1
);
312 return GNUTLS_E_MEMORY_ERROR
;
314 _gnutls_hash (td
, username
, strlen (username
));
315 _gnutls_hash (td
, ":", 1);
316 _gnutls_hash (td
, password
, strlen (password
));
318 _gnutls_hash_deinit (td
, res
);
320 td
= _gnutls_hash_init (GNUTLS_MAC_SHA1
);
323 return GNUTLS_E_MEMORY_ERROR
;
326 _gnutls_hash (td
, salt
, salt_size
);
327 _gnutls_hash (td
, res
, 20); /* 20 bytes is the output of sha1 */
329 _gnutls_hash_deinit (td
, digest
);
335 _gnutls_calc_srp_x (char *username
, char *password
, opaque
* salt
,
336 size_t salt_size
, size_t * size
, void *digest
)
339 return _gnutls_calc_srp_sha (username
, password
, salt
,
340 salt_size
, size
, digest
);
344 /* S = (B - k*g^x) ^ (a + u * x) % N
345 * this is our shared key (client premaster secret)
348 _gnutls_calc_srp_S2 (mpi_t B
, mpi_t g
, mpi_t x
, mpi_t a
, mpi_t u
, mpi_t n
)
350 mpi_t S
= NULL
, tmp1
= NULL
, tmp2
= NULL
;
351 mpi_t tmp4
= NULL
, tmp3
= NULL
, k
= NULL
;
353 S
= _gnutls_mpi_alloc_like (n
);
357 tmp1
= _gnutls_mpi_alloc_like (n
);
358 tmp2
= _gnutls_mpi_alloc_like (n
);
359 tmp3
= _gnutls_mpi_alloc_like (n
);
360 if (tmp1
== NULL
|| tmp2
== NULL
|| tmp3
== NULL
)
365 k
= _gnutls_calc_srp_u (n
, g
, n
);
372 _gnutls_mpi_powm (tmp1
, g
, x
, n
); /* g^x */
373 _gnutls_mpi_mulm (tmp3
, tmp1
, k
, n
); /* k*g^x mod n */
374 _gnutls_mpi_subm (tmp2
, B
, tmp3
, n
);
376 tmp4
= _gnutls_mpi_alloc_like (n
);
380 _gnutls_mpi_mul (tmp1
, u
, x
);
381 _gnutls_mpi_add (tmp4
, a
, tmp1
);
382 _gnutls_mpi_powm (S
, tmp2
, tmp4
, n
);
384 _gnutls_mpi_release (&tmp1
);
385 _gnutls_mpi_release (&tmp2
);
386 _gnutls_mpi_release (&tmp3
);
387 _gnutls_mpi_release (&tmp4
);
388 _gnutls_mpi_release (&k
);
393 _gnutls_mpi_release (&k
);
394 _gnutls_mpi_release (&tmp1
);
395 _gnutls_mpi_release (&tmp2
);
396 _gnutls_mpi_release (&tmp3
);
397 _gnutls_mpi_release (&tmp4
);
398 _gnutls_mpi_release (&S
);
403 * gnutls_srp_free_client_credentials - Used to free an allocated gnutls_srp_client_credentials_t structure
404 * @sc: is an #gnutls_srp_client_credentials_t structure.
406 * This structure is complex enough to manipulate directly thus
407 * this helper function is provided in order to free (deallocate) it.
411 gnutls_srp_free_client_credentials (gnutls_srp_client_credentials_t sc
)
413 gnutls_free (sc
->username
);
414 gnutls_free (sc
->password
);
419 * gnutls_srp_allocate_client_credentials - Used to allocate an gnutls_srp_server_credentials_t structure
420 * @sc: is a pointer to an #gnutls_srp_server_credentials_t structure.
422 * This structure is complex enough to manipulate directly thus
423 * this helper function is provided in order to allocate it.
425 * Returns 0 on success.
428 gnutls_srp_allocate_client_credentials (gnutls_srp_client_credentials_t
* sc
)
430 *sc
= gnutls_calloc (1, sizeof (srp_client_credentials_st
));
433 return GNUTLS_E_MEMORY_ERROR
;
439 * gnutls_srp_set_client_credentials - Used to set the username/password, in a gnutls_srp_client_credentials_t structure
440 * @res: is an #gnutls_srp_client_credentials_t structure.
441 * @username: is the user's userid
442 * @password: is the user's password
444 * This function sets the username and password, in a gnutls_srp_client_credentials_t structure.
445 * Those will be used in SRP authentication. @username and @password should be ASCII
446 * strings or UTF-8 strings prepared using the "SASLprep" profile of "stringprep".
448 * Returns 0 on success.
451 gnutls_srp_set_client_credentials (gnutls_srp_client_credentials_t res
,
452 const char *username
, const char *password
)
455 if (username
== NULL
|| password
== NULL
)
458 return GNUTLS_E_INVALID_REQUEST
;
461 res
->username
= gnutls_strdup (username
);
462 if (res
->username
== NULL
)
463 return GNUTLS_E_MEMORY_ERROR
;
465 res
->password
= gnutls_strdup (password
);
466 if (res
->password
== NULL
)
468 gnutls_free (res
->username
);
469 return GNUTLS_E_MEMORY_ERROR
;
476 * gnutls_srp_free_server_credentials - Used to free an allocated gnutls_srp_server_credentials_t structure
477 * @sc: is an #gnutls_srp_server_credentials_t structure.
479 * This structure is complex enough to manipulate directly thus
480 * this helper function is provided in order to free (deallocate) it.
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
);
493 * gnutls_srp_allocate_server_credentials - Used to allocate an gnutls_srp_server_credentials_t structure
494 * @sc: is a pointer to an #gnutls_srp_server_credentials_t structure.
496 * This structure is complex enough to manipulate directly thus
497 * this helper function is provided in order to allocate it.
499 * Returns 0 on success.
502 gnutls_srp_allocate_server_credentials (gnutls_srp_server_credentials_t
* sc
)
504 *sc
= gnutls_calloc (1, sizeof (srp_server_cred_st
));
507 return GNUTLS_E_MEMORY_ERROR
;
513 * gnutls_srp_set_server_credentials_file - Used to set the password files, in a gnutls_srp_server_credentials_t structure
514 * @res: is an #gnutls_srp_server_credentials_t structure.
515 * @password_file: is the SRP password file (tpasswd)
516 * @password_conf_file: is the SRP password conf file (tpasswd.conf)
518 * This function sets the password files, in a gnutls_srp_server_credentials_t structure.
519 * Those password files hold usernames and verifiers and will be used for SRP authentication.
521 * Returns 0 on success.
525 gnutls_srp_set_server_credentials_file (gnutls_srp_server_credentials_t
526 res
, const char *password_file
,
527 const char *password_conf_file
)
530 if (password_file
== NULL
|| password_conf_file
== NULL
)
533 return GNUTLS_E_INVALID_REQUEST
;
536 /* Check if the files can be opened */
537 if (_gnutls_file_exists (password_file
) != 0)
540 return GNUTLS_E_FILE_ERROR
;
543 if (_gnutls_file_exists (password_conf_file
) != 0)
546 return GNUTLS_E_FILE_ERROR
;
549 res
->password_file
= gnutls_strdup (password_file
);
550 if (res
->password_file
== NULL
)
553 return GNUTLS_E_MEMORY_ERROR
;
556 res
->password_conf_file
= gnutls_strdup (password_conf_file
);
557 if (res
->password_conf_file
== NULL
)
560 gnutls_free (res
->password_file
);
561 res
->password_file
= NULL
;
562 return GNUTLS_E_MEMORY_ERROR
;
570 * gnutls_srp_set_server_credentials_function - Used to set a callback to retrieve the user's SRP credentials
571 * @cred: is a #gnutls_srp_server_credentials_t structure.
572 * @func: is the callback function
574 * This function can be used to set a callback to retrieve the user's SRP credentials.
575 * The callback's function form is:
576 * int (*callback)(gnutls_session_t, const char* username,
577 * gnutls_datum_t* salt, gnutls_datum_t *verifier, gnutls_datum_t* g,
578 * gnutls_datum_t* n);
580 * @username contains the actual username.
581 * The @salt, @verifier, @generator and @prime must be filled
582 * in using the gnutls_malloc(). For convenience @prime and @generator
583 * may also be one of the static parameters defined in extra.h.
585 * In case the callback returned a negative number then gnutls will
586 * assume that the username does not exist.
588 * In order to prevent attackers from guessing valid usernames,
589 * if a user does not exist, g and n values should be filled in
590 * using a random user's parameters. In that case the callback must
591 * return the special value (1).
593 * The callback function will only be called once per handshake.
594 * The callback function should return 0 on success, while
595 * -1 indicates an error.
599 gnutls_srp_set_server_credentials_function (gnutls_srp_server_credentials_t
601 gnutls_srp_server_credentials_function
604 cred
->pwd_callback
= func
;
608 * gnutls_srp_set_client_credentials_function - Used to set a callback to retrieve the username and password
609 * @cred: is a #gnutls_srp_server_credentials_t structure.
610 * @func: is the callback function
612 * This function can be used to set a callback to retrieve the username and
613 * password for client SRP authentication.
614 * The callback's function form is:
615 * int (*callback)(gnutls_session_t, unsigned int times, char** username,
618 * The @username and @password must be allocated using gnutls_malloc().
619 * @times will be 0 the first time called, and 1 the second.
620 * @username and @password should be ASCII strings or UTF-8 strings
621 * prepared using the "SASLprep" profile of "stringprep".
623 * The callback function will be called once or twice per handshake.
624 * The first time called, is before the ciphersuite is negotiated.
625 * At that time if the callback returns a negative error code,
626 * the callback will be called again if SRP has been
627 * negotiated. This uses a special TLS-SRP idiom in order to avoid
628 * asking the user for SRP password and username if the server does
631 * The callback should not return a negative error code the second
632 * time called, since the handshake procedure will be aborted.
634 * The callback function should return 0 on success.
635 * -1 indicates an error.
639 gnutls_srp_set_client_credentials_function (gnutls_srp_client_credentials_t
641 gnutls_srp_client_credentials_function
644 cred
->get_function
= func
;
649 * gnutls_srp_server_get_username - This function returns the username of the peer
650 * @session: is a gnutls session
652 * This function will return the username of the peer. This should only be
653 * called in case of SRP authentication and in case of a server.
654 * Returns NULL in case of an error.
658 gnutls_srp_server_get_username (gnutls_session_t session
)
660 srp_server_auth_info_t info
;
662 CHECK_AUTH (GNUTLS_CRD_SRP
, NULL
);
664 info
= _gnutls_get_auth_info (session
);
667 return info
->username
;
671 * gnutls_srp_verifier - Used to calculate an SRP verifier
672 * @username: is the user's name
673 * @password: is the user's password
674 * @salt: should be some randomly generated bytes
675 * @generator: is the generator of the group
676 * @prime: is the group's prime
677 * @res: where the verifier will be stored.
679 * This function will create an SRP verifier, as specified in RFC2945.
680 * The @prime and @generator should be one of the static parameters defined
681 * in gnutls/extra.h or may be generated using the GCRYPT functions
682 * gcry_prime_generate() and gcry_prime_group_generator().
683 * The verifier will be allocated with @malloc and will be stored in @res using
688 gnutls_srp_verifier (const char *username
, const char *password
,
689 const gnutls_datum_t
* salt
,
690 const gnutls_datum_t
* generator
,
691 const gnutls_datum_t
* prime
, gnutls_datum_t
* res
)
695 size_t digest_size
= 20, size
;
698 ret
= _gnutls_calc_srp_sha (username
, password
, salt
->data
,
699 salt
->size
, &digest_size
, digest
);
707 if (_gnutls_mpi_scan_nz (&_n
, prime
->data
, &size
))
710 return GNUTLS_E_MPI_SCAN_FAILED
;
713 size
= generator
->size
;
714 if (_gnutls_mpi_scan_nz (&_g
, generator
->data
, &size
))
717 return GNUTLS_E_MPI_SCAN_FAILED
;
720 ret
= _gnutls_srp_gx (digest
, 20, &res
->data
, _g
, _n
, malloc
);
731 #endif /* ENABLE_SRP */