Tizen 2.0 Release
[external/libgnutls26.git] / lib / gnutls_srp.c
1 /*
2  * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2008, 2009, 2010 Free
3  * Software Foundation, Inc.
4  *
5  * Author: Nikos Mavrogiannopoulos
6  *
7  * This file is part of GnuTLS.
8  *
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.
13  *
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.
18  *
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
23  *
24  */
25
26 #include <gnutls_int.h>
27 #include <gnutls_errors.h>
28 #include <auth_srp.h>
29 #include <gnutls_state.h>
30
31 #ifdef ENABLE_SRP
32
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>
38
39 #include "debug.h"
40
41
42 /* Here functions for SRP (like g^x mod n) are defined 
43  */
44
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)
48 {
49   bigint_t x, e;
50   size_t result_size;
51   int ret;
52
53   if (_gnutls_mpi_scan_nz (&x, text, textsize))
54     {
55       gnutls_assert ();
56       return GNUTLS_E_MPI_SCAN_FAILED;
57     }
58
59   e = _gnutls_mpi_alloc_like (prime);
60   if (e == NULL)
61     {
62       gnutls_assert ();
63       _gnutls_mpi_release (&x);
64       return GNUTLS_E_MEMORY_ERROR;
65     }
66
67   /* e = g^x mod prime (n) */
68   _gnutls_mpi_powm (e, g, x, prime);
69   _gnutls_mpi_release (&x);
70
71   ret = _gnutls_mpi_print (e, NULL, &result_size);
72   if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
73     {
74       *result = galloc_func (result_size);
75       if ((*result) == NULL)
76         return GNUTLS_E_MEMORY_ERROR;
77
78       _gnutls_mpi_print (e, *result, &result_size);
79       ret = result_size;
80     }
81   else
82     {
83       gnutls_assert ();
84       ret = GNUTLS_E_MPI_PRINT_FAILED;
85     }
86
87   _gnutls_mpi_release (&e);
88
89   return ret;
90
91 }
92
93
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.
98  */
99 bigint_t
100 _gnutls_calc_srp_B (bigint_t * ret_b, bigint_t g, bigint_t n, bigint_t v)
101 {
102   bigint_t tmpB = NULL, tmpV = NULL;
103   bigint_t b = NULL, B = NULL, k = NULL;
104   int bits;
105
106
107   /* calculate:  B = (k*v + g^b) % N 
108    */
109   bits = _gnutls_mpi_get_nbits (n);
110
111   tmpV = _gnutls_mpi_alloc_like (n);
112
113   if (tmpV == NULL)
114     {
115       gnutls_assert ();
116       goto error;
117     }
118
119   b = _gnutls_mpi_randomize (NULL, bits, GNUTLS_RND_RANDOM);
120
121   tmpB = _gnutls_mpi_new (bits);
122   if (tmpB == NULL)
123     {
124       gnutls_assert ();
125       goto error;
126     }
127
128   B = _gnutls_mpi_new (bits);
129   if (B == NULL)
130     {
131       gnutls_assert ();
132       goto error;
133     }
134
135   k = _gnutls_calc_srp_u (n, g, n);
136   if (k == NULL)
137     {
138       gnutls_assert ();
139       goto error;
140     }
141
142   _gnutls_mpi_mulm (tmpV, k, v, n);
143   _gnutls_mpi_powm (tmpB, g, b, n);
144
145   _gnutls_mpi_addm (B, tmpV, tmpB, n);
146
147   _gnutls_mpi_release (&k);
148   _gnutls_mpi_release (&tmpB);
149   _gnutls_mpi_release (&tmpV);
150
151   if (ret_b)
152     *ret_b = b;
153   else
154     _gnutls_mpi_release (&b);
155
156   return B;
157
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;
165
166 }
167
168 /* This calculates the SHA1(A | B)
169  * A and B will be left-padded with zeros to fill n_size.
170  */
171 bigint_t
172 _gnutls_calc_srp_u (bigint_t A, bigint_t B, bigint_t n)
173 {
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;
180
181   /* get the size of n in bytes */
182   _gnutls_mpi_print (n, NULL, &n_size);
183
184   _gnutls_mpi_print (A, NULL, &a_size);
185   _gnutls_mpi_print (B, NULL, &b_size);
186
187   if (a_size > n_size || b_size > n_size)
188     {
189       gnutls_assert ();
190       return NULL;              /* internal error */
191     }
192
193   holder_size = n_size + n_size;
194
195   holder = gnutls_calloc (1, holder_size);
196   if (holder == NULL)
197     return NULL;
198
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);
201
202   ret = _gnutls_hash_init (&td, GNUTLS_MAC_SHA1);
203   if (ret < 0)
204     {
205       gnutls_free (holder);
206       gnutls_assert ();
207       return NULL;
208     }
209   _gnutls_hash (&td, holder, holder_size);
210   _gnutls_hash_deinit (&td, hd);
211
212   /* convert the bytes of hd to integer
213    */
214   hash_size = 20;               /* SHA */
215   ret = _gnutls_mpi_scan_nz (&res, hd, hash_size);
216   gnutls_free (holder);
217
218   if (ret < 0)
219     {
220       gnutls_assert ();
221       return NULL;
222     }
223
224   return res;
225 }
226
227 /* S = (A * v^u) ^ b % N 
228  * this is our shared key (server premaster secret)
229  */
230 bigint_t
231 _gnutls_calc_srp_S1 (bigint_t A, bigint_t b, bigint_t u, bigint_t v,
232                      bigint_t n)
233 {
234   bigint_t tmp1 = NULL, tmp2 = NULL;
235   bigint_t S = NULL;
236
237   S = _gnutls_mpi_alloc_like (n);
238   if (S == NULL)
239     return NULL;
240
241   tmp1 = _gnutls_mpi_alloc_like (n);
242   tmp2 = _gnutls_mpi_alloc_like (n);
243
244   if (tmp1 == NULL || tmp2 == NULL)
245     goto freeall;
246
247   _gnutls_mpi_powm (tmp1, v, u, n);
248   _gnutls_mpi_mulm (tmp2, A, tmp1, n);
249   _gnutls_mpi_powm (S, tmp2, b, n);
250
251   _gnutls_mpi_release (&tmp1);
252   _gnutls_mpi_release (&tmp2);
253
254   return S;
255
256 freeall:
257   _gnutls_mpi_release (&tmp1);
258   _gnutls_mpi_release (&tmp2);
259   return NULL;
260 }
261
262 /* A = g^a % N 
263  * returns A and a (which is random)
264  */
265 bigint_t
266 _gnutls_calc_srp_A (bigint_t * a, bigint_t g, bigint_t n)
267 {
268   bigint_t tmpa;
269   bigint_t A;
270   int bits;
271
272   bits = _gnutls_mpi_get_nbits (n);
273   tmpa = _gnutls_mpi_randomize (NULL, bits, GNUTLS_RND_RANDOM);
274
275   A = _gnutls_mpi_new (bits);
276   if (A == NULL)
277     {
278       gnutls_assert ();
279       _gnutls_mpi_release (&tmpa);
280       return NULL;
281     }
282   _gnutls_mpi_powm (A, g, tmpa, n);
283
284   if (a != NULL)
285     *a = tmpa;
286   else
287     _gnutls_mpi_release (&tmpa);
288
289   return A;
290 }
291
292 /* generate x = SHA(s | SHA(U | ":" | p))
293  * The output is exactly 20 bytes
294  */
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)
299 {
300   digest_hd_st td;
301   opaque res[MAX_HASH_SIZE];
302   int ret;
303
304   *size = 20;
305
306   ret = _gnutls_hash_init (&td, GNUTLS_MAC_SHA1);
307   if (ret < 0)
308     {
309       return GNUTLS_E_MEMORY_ERROR;
310     }
311   _gnutls_hash (&td, username, strlen (username));
312   _gnutls_hash (&td, ":", 1);
313   _gnutls_hash (&td, password, strlen (password));
314
315   _gnutls_hash_deinit (&td, res);
316
317   ret = _gnutls_hash_init (&td, GNUTLS_MAC_SHA1);
318   if (ret < 0)
319     {
320       return GNUTLS_E_MEMORY_ERROR;
321     }
322
323   _gnutls_hash (&td, salt, salt_size);
324   _gnutls_hash (&td, res, 20);  /* 20 bytes is the output of sha1 */
325
326   _gnutls_hash_deinit (&td, digest);
327
328   return 0;
329 }
330
331 int
332 _gnutls_calc_srp_x (char *username, char *password, opaque * salt,
333                     size_t salt_size, size_t * size, void *digest)
334 {
335
336   return _gnutls_calc_srp_sha (username, password, salt,
337                                salt_size, size, digest);
338 }
339
340
341 /* S = (B - k*g^x) ^ (a + u * x) % N
342  * this is our shared key (client premaster secret)
343  */
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)
347 {
348   bigint_t S = NULL, tmp1 = NULL, tmp2 = NULL;
349   bigint_t tmp4 = NULL, tmp3 = NULL, k = NULL;
350
351   S = _gnutls_mpi_alloc_like (n);
352   if (S == NULL)
353     return NULL;
354
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)
359     {
360       goto freeall;
361     }
362
363   k = _gnutls_calc_srp_u (n, g, n);
364   if (k == NULL)
365     {
366       gnutls_assert ();
367       goto freeall;
368     }
369
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);
373
374   tmp4 = _gnutls_mpi_alloc_like (n);
375   if (tmp4 == NULL)
376     goto freeall;
377
378   _gnutls_mpi_mul (tmp1, u, x);
379   _gnutls_mpi_add (tmp4, a, tmp1);
380   _gnutls_mpi_powm (S, tmp2, tmp4, n);
381
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);
387
388   return S;
389
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;
398 }
399
400 /**
401  * gnutls_srp_free_client_credentials:
402  * @sc: is a #gnutls_srp_client_credentials_t structure.
403  *
404  * This structure is complex enough to manipulate directly thus
405  * this helper function is provided in order to free (deallocate) it.
406  **/
407 void
408 gnutls_srp_free_client_credentials (gnutls_srp_client_credentials_t sc)
409 {
410   gnutls_free (sc->username);
411   gnutls_free (sc->password);
412   gnutls_free (sc);
413 }
414
415 /**
416  * gnutls_srp_allocate_client_credentials:
417  * @sc: is a pointer to a #gnutls_srp_server_credentials_t structure.
418  *
419  * This structure is complex enough to manipulate directly thus
420  * this helper function is provided in order to allocate it.
421  *
422  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or an
423  *   error code.
424  **/
425 int
426 gnutls_srp_allocate_client_credentials (gnutls_srp_client_credentials_t * sc)
427 {
428   *sc = gnutls_calloc (1, sizeof (srp_client_credentials_st));
429
430   if (*sc == NULL)
431     return GNUTLS_E_MEMORY_ERROR;
432
433   return 0;
434 }
435
436 /**
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
441  *
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".
447  *
448  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or an
449  *   error code.
450  **/
451 int
452 gnutls_srp_set_client_credentials (gnutls_srp_client_credentials_t res,
453                                    const char *username, const char *password)
454 {
455
456   if (username == NULL || password == NULL)
457     {
458       gnutls_assert ();
459       return GNUTLS_E_INVALID_REQUEST;
460     }
461
462   res->username = gnutls_strdup (username);
463   if (res->username == NULL)
464     return GNUTLS_E_MEMORY_ERROR;
465
466   res->password = gnutls_strdup (password);
467   if (res->password == NULL)
468     {
469       gnutls_free (res->username);
470       return GNUTLS_E_MEMORY_ERROR;
471     }
472
473   return 0;
474 }
475
476 /**
477  * gnutls_srp_free_server_credentials:
478  * @sc: is a #gnutls_srp_server_credentials_t structure.
479  *
480  * This structure is complex enough to manipulate directly thus
481  * this helper function is provided in order to free (deallocate) it.
482  **/
483 void
484 gnutls_srp_free_server_credentials (gnutls_srp_server_credentials_t sc)
485 {
486   gnutls_free (sc->password_file);
487   gnutls_free (sc->password_conf_file);
488
489   gnutls_free (sc);
490 }
491
492 /**
493  * gnutls_srp_allocate_server_credentials:
494  * @sc: is a pointer to a #gnutls_srp_server_credentials_t structure.
495  *
496  * This structure is complex enough to manipulate directly thus this
497  * helper function is provided in order to allocate it.
498  *
499  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or an
500  *   error code.
501  **/
502 int
503 gnutls_srp_allocate_server_credentials (gnutls_srp_server_credentials_t * sc)
504 {
505   *sc = gnutls_calloc (1, sizeof (srp_server_cred_st));
506
507   if (*sc == NULL)
508     return GNUTLS_E_MEMORY_ERROR;
509
510   return 0;
511 }
512
513 /**
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)
518  *
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.
523  *
524  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or an
525  *   error code.
526  **/
527 int
528 gnutls_srp_set_server_credentials_file (gnutls_srp_server_credentials_t res,
529                                         const char *password_file,
530                                         const char *password_conf_file)
531 {
532
533   if (password_file == NULL || password_conf_file == NULL)
534     {
535       gnutls_assert ();
536       return GNUTLS_E_INVALID_REQUEST;
537     }
538
539   /* Check if the files can be opened */
540   if (_gnutls_file_exists (password_file) != 0)
541     {
542       gnutls_assert ();
543       return GNUTLS_E_FILE_ERROR;
544     }
545
546   if (_gnutls_file_exists (password_conf_file) != 0)
547     {
548       gnutls_assert ();
549       return GNUTLS_E_FILE_ERROR;
550     }
551
552   res->password_file = gnutls_strdup (password_file);
553   if (res->password_file == NULL)
554     {
555       gnutls_assert ();
556       return GNUTLS_E_MEMORY_ERROR;
557     }
558
559   res->password_conf_file = gnutls_strdup (password_conf_file);
560   if (res->password_conf_file == NULL)
561     {
562       gnutls_assert ();
563       gnutls_free (res->password_file);
564       res->password_file = NULL;
565       return GNUTLS_E_MEMORY_ERROR;
566     }
567
568   return 0;
569 }
570
571
572 /**
573  * gnutls_srp_set_server_credentials_function:
574  * @cred: is a #gnutls_srp_server_credentials_t structure.
575  * @func: is the callback function
576  *
577  * This function can be used to set a callback to retrieve the user's
578  * SRP credentials.  The callback's function form is:
579  *
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);
583  *
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.
588  *
589  * In case the callback returned a negative number then gnutls will
590  * assume that the username does not exist.
591  *
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).
596  *
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.
600  **/
601 void
602 gnutls_srp_set_server_credentials_function (gnutls_srp_server_credentials_t
603                                             cred,
604                                             gnutls_srp_server_credentials_function
605                                             * func)
606 {
607   cred->pwd_callback = func;
608 }
609
610 /**
611  * gnutls_srp_set_client_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
616  * username and password for client SRP authentication.  The
617  * callback's function form is:
618  *
619  * int (*callback)(gnutls_session_t, char** username, char**password);
620  *
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".
625  *
626  * The callback function will be called once per handshake before the
627  * initial hello message is sent.
628  *
629  * The callback should not return a negative error code the second
630  * time called, since the handshake procedure will be aborted.
631  *
632  * The callback function should return 0 on success.
633  * -1 indicates an error.
634  **/
635 void
636 gnutls_srp_set_client_credentials_function (gnutls_srp_client_credentials_t
637                                             cred,
638                                             gnutls_srp_client_credentials_function
639                                             * func)
640 {
641   cred->get_function = func;
642 }
643
644
645 /**
646  * gnutls_srp_server_get_username:
647  * @session: is a gnutls session
648  *
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.
652  *
653  * Returns: SRP username of the peer, or NULL in case of error.
654  **/
655 const char *
656 gnutls_srp_server_get_username (gnutls_session_t session)
657 {
658   srp_server_auth_info_t info;
659
660   CHECK_AUTH (GNUTLS_CRD_SRP, NULL);
661
662   info = _gnutls_get_auth_info (session);
663   if (info == NULL)
664     return NULL;
665   return info->username;
666 }
667
668 /**
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.
676  *
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().
682  *
683  * The verifier will be allocated with @malloc and will be stored in
684  * @res using binary format.
685  *
686  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or an
687  *   error code.
688  **/
689 int
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)
694 {
695   bigint_t _n, _g;
696   int ret;
697   size_t digest_size = 20, size;
698   opaque digest[20];
699
700   ret = _gnutls_calc_srp_sha (username, password, salt->data,
701                               salt->size, &digest_size, digest);
702   if (ret < 0)
703     {
704       gnutls_assert ();
705       return ret;
706     }
707
708   size = prime->size;
709   if (_gnutls_mpi_scan_nz (&_n, prime->data, size))
710     {
711       gnutls_assert ();
712       return GNUTLS_E_MPI_SCAN_FAILED;
713     }
714
715   size = generator->size;
716   if (_gnutls_mpi_scan_nz (&_g, generator->data, size))
717     {
718       gnutls_assert ();
719       return GNUTLS_E_MPI_SCAN_FAILED;
720     }
721
722   ret = _gnutls_srp_gx (digest, 20, &res->data, _g, _n, malloc);
723   if (ret < 0)
724     {
725       gnutls_assert ();
726       return ret;
727     }
728   res->size = ret;
729
730   return 0;
731 }
732
733 /**
734  * gnutls_srp_set_prime_bits:
735  * @session: is a #gnutls_session_t structure.
736  * @bits: is the number of bits
737  *
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.
740  *
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.
745  *
746  * This function has no effect in server side.
747  *
748  * Since: 2.6.0
749  **/
750 void
751 gnutls_srp_set_prime_bits (gnutls_session_t session, unsigned int bits)
752 {
753   session->internals.srp_prime_bits = bits;
754 }
755
756 #endif /* ENABLE_SRP */