Tizen 2.0 Release
[external/libgnutls26.git] / lib / auth_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
28 #ifdef ENABLE_SRP
29
30 #include "gnutls_errors.h"
31 #include "auth_srp_passwd.h"
32 #include "gnutls_auth.h"
33 #include "gnutls_auth.h"
34 #include "gnutls_srp.h"
35 #include "gnutls_num.h"
36 #include "auth_srp.h"
37 #include <gnutls_str.h>
38 #include <gnutls_datum.h>
39 #include <ext_srp.h>
40
41 const mod_auth_st srp_auth_struct = {
42   "SRP",
43   NULL,
44   NULL,
45   _gnutls_gen_srp_server_kx,
46   _gnutls_gen_srp_client_kx,
47   NULL,
48   NULL,
49
50   NULL,
51   NULL,                         /* certificate */
52   _gnutls_proc_srp_server_kx,
53   _gnutls_proc_srp_client_kx,
54   NULL,
55   NULL
56 };
57
58
59 #define _b session->key->b
60 #define B session->key->B
61 #define _a session->key->a
62 #define A session->key->A
63 #define N session->key->client_p
64 #define G session->key->client_g
65 #define V session->key->x
66 #define S session->key->KEY
67
68 /* Checks if b%n==0 which is a fatal srp error.
69  * Returns a proper error code in that case, and 0 when
70  * all are ok.
71  */
72 inline static int
73 check_b_mod_n (bigint_t b, bigint_t n)
74 {
75   int ret;
76   bigint_t r;
77
78   r = _gnutls_mpi_mod (b, n);
79
80   if (r == NULL)
81     {
82       gnutls_assert ();
83       return GNUTLS_E_MEMORY_ERROR;
84     }
85
86   ret = _gnutls_mpi_cmp_ui (r, 0);
87
88   _gnutls_mpi_release (&r);
89
90   if (ret == 0)
91     {
92       gnutls_assert ();
93       return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
94     }
95
96   return 0;
97 }
98
99 /* Checks if a%n==0,+1,-1%n which is a fatal srp error.
100  * Returns a proper error code in that case, and 0 when
101  * all are ok.
102  */
103 inline static int
104 check_a_mod_n (bigint_t a, bigint_t n)
105 {
106   int ret, err = 0;
107   bigint_t r;
108
109   r = _gnutls_mpi_mod (a, n);
110   if (r == NULL)
111     {
112       gnutls_assert ();
113       return GNUTLS_E_MEMORY_ERROR;
114     }
115
116   ret = _gnutls_mpi_cmp_ui (r, 0);
117   if (ret == 0) err = 1;
118
119   ret = _gnutls_mpi_cmp_ui (r, 1);
120   if (ret == 0) err = 1;
121
122   _gnutls_mpi_add_ui(r, r, 1);
123   ret = _gnutls_mpi_cmp (r, n);
124   if (ret == 0) err = 1;
125
126   _gnutls_mpi_release (&r);
127
128   if (err != 0)
129     {
130       gnutls_assert ();
131       return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
132     }
133
134   return 0;
135 }
136
137
138 /* Send the first key exchange message ( g, n, s) and append the verifier algorithm number 
139  * Data is allocated by the caller, and should have data_size size.
140  */
141 int
142 _gnutls_gen_srp_server_kx (gnutls_session_t session, opaque ** data)
143 {
144   int ret;
145   uint8_t *data_n, *data_s;
146   uint8_t *data_g;
147   char *username;
148   SRP_PWD_ENTRY *pwd_entry;
149   srp_server_auth_info_t info;
150   ssize_t data_size;
151   size_t n_b, tmp_size;
152   char buf[64];
153   uint8_t *data_b;
154   extension_priv_data_t epriv;
155   srp_ext_st *priv;
156
157   ret = _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_SRP, &epriv);
158   if (ret < 0)                  /* peer didn't send a username */
159     {
160       gnutls_assert ();
161       return GNUTLS_E_UNKNOWN_SRP_USERNAME;
162     }
163   priv = epriv.ptr;
164
165   if ((ret =
166        _gnutls_auth_info_set (session, GNUTLS_CRD_SRP,
167                               sizeof (srp_server_auth_info_st), 1)) < 0)
168     {
169       gnutls_assert ();
170       return ret;
171     }
172
173   info = _gnutls_get_auth_info (session);
174   username = info->username;
175
176   _gnutls_str_cpy (username, MAX_USERNAME_SIZE, priv->username);
177
178   ret = _gnutls_srp_pwd_read_entry (session, username, &pwd_entry);
179
180   if (ret < 0)
181     {
182       gnutls_assert ();
183       return ret;
184     }
185
186   /* copy from pwd_entry to local variables (actually in session) */
187   tmp_size = pwd_entry->g.size;
188   if (_gnutls_mpi_scan_nz (&G, pwd_entry->g.data, tmp_size) < 0)
189     {
190       gnutls_assert ();
191       return GNUTLS_E_MPI_SCAN_FAILED;
192     }
193
194   tmp_size = pwd_entry->n.size;
195   if (_gnutls_mpi_scan_nz (&N, pwd_entry->n.data, tmp_size) < 0)
196     {
197       gnutls_assert ();
198       return GNUTLS_E_MPI_SCAN_FAILED;
199     }
200
201   tmp_size = pwd_entry->v.size;
202   if (_gnutls_mpi_scan_nz (&V, pwd_entry->v.data, tmp_size) < 0)
203     {
204       gnutls_assert ();
205       return GNUTLS_E_MPI_SCAN_FAILED;
206     }
207
208   /* Calculate:  B = (k*v + g^b) % N 
209    */
210   B = _gnutls_calc_srp_B (&_b, G, N, V);
211   if (B == NULL)
212     {
213       gnutls_assert ();
214       return GNUTLS_E_MEMORY_ERROR;
215     }
216
217   if (_gnutls_mpi_print (B, NULL, &n_b) != GNUTLS_E_SHORT_MEMORY_BUFFER)
218     {
219       gnutls_assert ();
220       return GNUTLS_E_MPI_PRINT_FAILED;
221     }
222
223
224   /* Allocate size to hold the N, g, s, B 
225    */
226
227   data_size = (pwd_entry->n.size + 2 + pwd_entry->g.size + 2 +
228                pwd_entry->salt.size + 1) + (n_b + 2);
229
230   (*data) = gnutls_malloc (data_size);
231   if ((*data) == NULL)
232     {
233       gnutls_assert ();
234       return GNUTLS_E_MEMORY_ERROR;
235     }
236
237   /* copy N (mod n) 
238    */
239   data_n = *data;
240   _gnutls_write_datum16 (data_n, pwd_entry->n);
241
242
243   /* copy G (generator) to data 
244    */
245   data_g = &data_n[2 + pwd_entry->n.size];
246   _gnutls_write_datum16 (data_g, pwd_entry->g);
247
248
249   /* copy the salt 
250    */
251   data_s = &data_g[2 + pwd_entry->g.size];
252   _gnutls_write_datum8 (data_s, pwd_entry->salt);
253
254
255   /* Copy the B value
256    */
257
258   data_b = &data_s[1 + pwd_entry->salt.size];
259   if (_gnutls_mpi_print (B, &data_b[2], &n_b) != 0)
260     {
261       gnutls_assert ();
262       return GNUTLS_E_MPI_PRINT_FAILED;
263     }
264
265   _gnutls_write_uint16 (n_b, data_b);
266
267   _gnutls_hard_log ("INT: SRP B[%d]: %s\n", (int) n_b,
268                     _gnutls_bin2hex (&data_b[2], n_b, buf, sizeof (buf),
269                                      NULL));
270
271   _gnutls_srp_entry_free (pwd_entry);
272
273   return data_size;
274 }
275
276 /* return A = g^a % N */
277 int
278 _gnutls_gen_srp_client_kx (gnutls_session_t session, opaque ** data)
279 {
280   size_t n_a;
281   int ret;
282   uint8_t *data_a;
283   char *username, *password;
284   char buf[64];
285   gnutls_srp_client_credentials_t cred;
286   extension_priv_data_t epriv;
287   srp_ext_st *priv;
288
289   ret = _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_SRP, &epriv);
290   if (ret < 0)                  /* peer didn't send a username */
291     {
292       gnutls_assert ();
293       return GNUTLS_E_UNKNOWN_SRP_USERNAME;
294     }
295   priv = epriv.ptr;
296
297   cred = (gnutls_srp_client_credentials_t)
298     _gnutls_get_cred (session->key, GNUTLS_CRD_SRP, NULL);
299
300   if (cred == NULL)
301     {
302       gnutls_assert ();
303       return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
304     }
305
306   if (priv->username == NULL)
307     {
308       username = cred->username;
309       password = cred->password;
310     }
311   else
312     {
313
314       username = priv->username;
315       password = priv->password;
316     }
317
318   if (username == NULL || password == NULL)
319     {
320       gnutls_assert ();
321       return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
322     }
323
324   /* calc A = g^a % N 
325    */
326   if (G == NULL || N == NULL)
327     {
328       gnutls_assert ();
329       return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
330     }
331
332   A = _gnutls_calc_srp_A (&_a, G, N);
333   if (A == NULL)
334     {
335       gnutls_assert ();
336       return GNUTLS_E_MEMORY_ERROR;
337     }
338
339   /* Rest of SRP calculations 
340    */
341
342   /* calculate u */
343   session->key->u = _gnutls_calc_srp_u (A, B, N);
344   if (session->key->u == NULL)
345     {
346       gnutls_assert ();
347       return GNUTLS_E_MEMORY_ERROR;
348     }
349
350   _gnutls_mpi_log ("SRP U: ", session->key->u);
351
352   /* S = (B - g^x) ^ (a + u * x) % N */
353   S = _gnutls_calc_srp_S2 (B, G, session->key->x, _a, session->key->u, N);
354   if (S == NULL)
355     {
356       gnutls_assert ();
357       return GNUTLS_E_MEMORY_ERROR;
358     }
359
360   _gnutls_mpi_log ("SRP B: ", B);
361
362   _gnutls_mpi_release (&_b);
363   _gnutls_mpi_release (&V);
364   _gnutls_mpi_release (&session->key->u);
365   _gnutls_mpi_release (&B);
366
367   ret = _gnutls_mpi_dprint (session->key->KEY, &session->key->key);
368   _gnutls_mpi_release (&S);
369
370   if (ret < 0)
371     {
372       gnutls_assert ();
373       return ret;
374     }
375
376   if (_gnutls_mpi_print (A, NULL, &n_a) != GNUTLS_E_SHORT_MEMORY_BUFFER)
377     {
378       gnutls_assert ();
379       return GNUTLS_E_MPI_PRINT_FAILED;
380     }
381
382   (*data) = gnutls_malloc (n_a + 2);
383   if ((*data) == NULL)
384     {
385       gnutls_assert ();
386       return GNUTLS_E_MEMORY_ERROR;
387     }
388
389   /* copy A */
390   data_a = (*data);
391   if (_gnutls_mpi_print (A, &data_a[2], &n_a) != 0)
392     {
393       gnutls_free (*data);
394       return GNUTLS_E_MPI_PRINT_FAILED;
395     }
396
397   _gnutls_hard_log ("INT: SRP A[%d]: %s\n", (int) n_a,
398                     _gnutls_bin2hex (&data_a[2], n_a, buf, sizeof (buf),
399                                      NULL));
400
401   _gnutls_mpi_release (&A);
402
403   _gnutls_write_uint16 (n_a, data_a);
404
405   return n_a + 2;
406 }
407
408
409 /* just read A and put it to session */
410 int
411 _gnutls_proc_srp_client_kx (gnutls_session_t session, opaque * data,
412                             size_t _data_size)
413 {
414   size_t _n_A;
415   ssize_t data_size = _data_size;
416   int ret;
417
418   DECR_LEN (data_size, 2);
419   _n_A = _gnutls_read_uint16 (&data[0]);
420
421   DECR_LEN (data_size, _n_A);
422   if (_gnutls_mpi_scan_nz (&A, &data[2], _n_A) || A == NULL)
423     {
424       gnutls_assert ();
425       return GNUTLS_E_MPI_SCAN_FAILED;
426     }
427
428   _gnutls_mpi_log ("SRP A: ", A);
429   _gnutls_mpi_log ("SRP B: ", B);
430
431   /* Checks if A % n == 0.
432    */
433   if ((ret = check_a_mod_n (A, N)) < 0)
434     {
435       gnutls_assert ();
436       return ret;
437     }
438
439   /* Start the SRP calculations.
440    * - Calculate u 
441    */
442   session->key->u = _gnutls_calc_srp_u (A, B, N);
443   if (session->key->u == NULL)
444     {
445       gnutls_assert ();
446       return GNUTLS_E_MEMORY_ERROR;
447     }
448
449   _gnutls_mpi_log ("SRP U: ", session->key->u);
450
451   /* S = (A * v^u) ^ b % N 
452    */
453   S = _gnutls_calc_srp_S1 (A, _b, session->key->u, V, N);
454   if (S == NULL)
455     {
456       gnutls_assert ();
457       return GNUTLS_E_MEMORY_ERROR;
458     }
459
460   _gnutls_mpi_log ("SRP S: ", S);
461
462   _gnutls_mpi_release (&A);
463   _gnutls_mpi_release (&_b);
464   _gnutls_mpi_release (&V);
465   _gnutls_mpi_release (&session->key->u);
466   _gnutls_mpi_release (&B);
467
468   ret = _gnutls_mpi_dprint (session->key->KEY, &session->key->key);
469   _gnutls_mpi_release (&S);
470
471   if (ret < 0)
472     {
473       gnutls_assert ();
474       return ret;
475     }
476
477   return 0;
478 }
479
480
481
482 /* Static parameters according to draft-ietf-tls-srp-07
483  * Note that if more parameters are added check_g_n()
484  * and _gnutls_srp_entry_free() should be changed.
485  */
486 static const unsigned char srp_params_1024[] = {
487   0xEE, 0xAF, 0x0A, 0xB9, 0xAD, 0xB3, 0x8D, 0xD6,
488   0x9C, 0x33, 0xF8, 0x0A, 0xFA, 0x8F, 0xC5, 0xE8,
489   0x60, 0x72, 0x61, 0x87, 0x75, 0xFF, 0x3C, 0x0B,
490   0x9E, 0xA2, 0x31, 0x4C, 0x9C, 0x25, 0x65, 0x76,
491   0xD6, 0x74, 0xDF, 0x74, 0x96, 0xEA, 0x81, 0xD3,
492   0x38, 0x3B, 0x48, 0x13, 0xD6, 0x92, 0xC6, 0xE0,
493   0xE0, 0xD5, 0xD8, 0xE2, 0x50, 0xB9, 0x8B, 0xE4,
494   0x8E, 0x49, 0x5C, 0x1D, 0x60, 0x89, 0xDA, 0xD1,
495   0x5D, 0xC7, 0xD7, 0xB4, 0x61, 0x54, 0xD6, 0xB6,
496   0xCE, 0x8E, 0xF4, 0xAD, 0x69, 0xB1, 0x5D, 0x49,
497   0x82, 0x55, 0x9B, 0x29, 0x7B, 0xCF, 0x18, 0x85,
498   0xC5, 0x29, 0xF5, 0x66, 0x66, 0x0E, 0x57, 0xEC,
499   0x68, 0xED, 0xBC, 0x3C, 0x05, 0x72, 0x6C, 0xC0,
500   0x2F, 0xD4, 0xCB, 0xF4, 0x97, 0x6E, 0xAA, 0x9A,
501   0xFD, 0x51, 0x38, 0xFE, 0x83, 0x76, 0x43, 0x5B,
502   0x9F, 0xC6, 0x1D, 0x2F, 0xC0, 0xEB, 0x06, 0xE3
503 };
504
505 static const unsigned char srp_generator = 0x02;
506
507 const gnutls_datum_t gnutls_srp_1024_group_prime = {
508   (void *) srp_params_1024, sizeof (srp_params_1024)
509 };
510
511 const gnutls_datum_t gnutls_srp_1024_group_generator = {
512   (void *) &srp_generator, sizeof (srp_generator)
513 };
514
515 static const unsigned char srp_params_1536[] = {
516   0x9D, 0xEF, 0x3C, 0xAF, 0xB9, 0x39, 0x27, 0x7A, 0xB1,
517   0xF1, 0x2A, 0x86, 0x17, 0xA4, 0x7B, 0xBB, 0xDB, 0xA5,
518   0x1D, 0xF4, 0x99, 0xAC, 0x4C, 0x80, 0xBE, 0xEE, 0xA9,
519   0x61, 0x4B, 0x19, 0xCC, 0x4D, 0x5F, 0x4F, 0x5F, 0x55,
520   0x6E, 0x27, 0xCB, 0xDE, 0x51, 0xC6, 0xA9, 0x4B, 0xE4,
521   0x60, 0x7A, 0x29, 0x15, 0x58, 0x90, 0x3B, 0xA0, 0xD0,
522   0xF8, 0x43, 0x80, 0xB6, 0x55, 0xBB, 0x9A, 0x22, 0xE8,
523   0xDC, 0xDF, 0x02, 0x8A, 0x7C, 0xEC, 0x67, 0xF0, 0xD0,
524   0x81, 0x34, 0xB1, 0xC8, 0xB9, 0x79, 0x89, 0x14, 0x9B,
525   0x60, 0x9E, 0x0B, 0xE3, 0xBA, 0xB6, 0x3D, 0x47, 0x54,
526   0x83, 0x81, 0xDB, 0xC5, 0xB1, 0xFC, 0x76, 0x4E, 0x3F,
527   0x4B, 0x53, 0xDD, 0x9D, 0xA1, 0x15, 0x8B, 0xFD, 0x3E,
528   0x2B, 0x9C, 0x8C, 0xF5, 0x6E, 0xDF, 0x01, 0x95, 0x39,
529   0x34, 0x96, 0x27, 0xDB, 0x2F, 0xD5, 0x3D, 0x24, 0xB7,
530   0xC4, 0x86, 0x65, 0x77, 0x2E, 0x43, 0x7D, 0x6C, 0x7F,
531   0x8C, 0xE4, 0x42, 0x73, 0x4A, 0xF7, 0xCC, 0xB7, 0xAE,
532   0x83, 0x7C, 0x26, 0x4A, 0xE3, 0xA9, 0xBE, 0xB8, 0x7F,
533   0x8A, 0x2F, 0xE9, 0xB8, 0xB5, 0x29, 0x2E, 0x5A, 0x02,
534   0x1F, 0xFF, 0x5E, 0x91, 0x47, 0x9E, 0x8C, 0xE7, 0xA2,
535   0x8C, 0x24, 0x42, 0xC6, 0xF3, 0x15, 0x18, 0x0F, 0x93,
536   0x49, 0x9A, 0x23, 0x4D, 0xCF, 0x76, 0xE3, 0xFE, 0xD1,
537   0x35, 0xF9, 0xBB
538 };
539
540 const gnutls_datum_t gnutls_srp_1536_group_prime = {
541   (void *) srp_params_1536, sizeof (srp_params_1536)
542 };
543
544 const gnutls_datum_t gnutls_srp_1536_group_generator = {
545   (void *) &srp_generator, sizeof (srp_generator)
546 };
547
548 static const unsigned char srp_params_2048[] = {
549   0xAC, 0x6B, 0xDB, 0x41, 0x32, 0x4A, 0x9A, 0x9B, 0xF1,
550   0x66, 0xDE, 0x5E, 0x13, 0x89, 0x58, 0x2F, 0xAF, 0x72,
551   0xB6, 0x65, 0x19, 0x87, 0xEE, 0x07, 0xFC, 0x31, 0x92,
552   0x94, 0x3D, 0xB5, 0x60, 0x50, 0xA3, 0x73, 0x29, 0xCB,
553   0xB4, 0xA0, 0x99, 0xED, 0x81, 0x93, 0xE0, 0x75, 0x77,
554   0x67, 0xA1, 0x3D, 0xD5, 0x23, 0x12, 0xAB, 0x4B, 0x03,
555   0x31, 0x0D, 0xCD, 0x7F, 0x48, 0xA9, 0xDA, 0x04, 0xFD,
556   0x50, 0xE8, 0x08, 0x39, 0x69, 0xED, 0xB7, 0x67, 0xB0,
557   0xCF, 0x60, 0x95, 0x17, 0x9A, 0x16, 0x3A, 0xB3, 0x66,
558   0x1A, 0x05, 0xFB, 0xD5, 0xFA, 0xAA, 0xE8, 0x29, 0x18,
559   0xA9, 0x96, 0x2F, 0x0B, 0x93, 0xB8, 0x55, 0xF9, 0x79,
560   0x93, 0xEC, 0x97, 0x5E, 0xEA, 0xA8, 0x0D, 0x74, 0x0A,
561   0xDB, 0xF4, 0xFF, 0x74, 0x73, 0x59, 0xD0, 0x41, 0xD5,
562   0xC3, 0x3E, 0xA7, 0x1D, 0x28, 0x1E, 0x44, 0x6B, 0x14,
563   0x77, 0x3B, 0xCA, 0x97, 0xB4, 0x3A, 0x23, 0xFB, 0x80,
564   0x16, 0x76, 0xBD, 0x20, 0x7A, 0x43, 0x6C, 0x64, 0x81,
565   0xF1, 0xD2, 0xB9, 0x07, 0x87, 0x17, 0x46, 0x1A, 0x5B,
566   0x9D, 0x32, 0xE6, 0x88, 0xF8, 0x77, 0x48, 0x54, 0x45,
567   0x23, 0xB5, 0x24, 0xB0, 0xD5, 0x7D, 0x5E, 0xA7, 0x7A,
568   0x27, 0x75, 0xD2, 0xEC, 0xFA, 0x03, 0x2C, 0xFB, 0xDB,
569   0xF5, 0x2F, 0xB3, 0x78, 0x61, 0x60, 0x27, 0x90, 0x04,
570   0xE5, 0x7A, 0xE6, 0xAF, 0x87, 0x4E, 0x73, 0x03, 0xCE,
571   0x53, 0x29, 0x9C, 0xCC, 0x04, 0x1C, 0x7B, 0xC3, 0x08,
572   0xD8, 0x2A, 0x56, 0x98, 0xF3, 0xA8, 0xD0, 0xC3, 0x82,
573   0x71, 0xAE, 0x35, 0xF8, 0xE9, 0xDB, 0xFB, 0xB6, 0x94,
574   0xB5, 0xC8, 0x03, 0xD8, 0x9F, 0x7A, 0xE4, 0x35, 0xDE,
575   0x23, 0x6D, 0x52, 0x5F, 0x54, 0x75, 0x9B, 0x65, 0xE3,
576   0x72, 0xFC, 0xD6, 0x8E, 0xF2, 0x0F, 0xA7, 0x11, 0x1F,
577   0x9E, 0x4A, 0xFF, 0x73
578 };
579
580 const gnutls_datum_t gnutls_srp_2048_group_prime = {
581   (void *) srp_params_2048, sizeof (srp_params_2048)
582 };
583
584 const gnutls_datum_t gnutls_srp_2048_group_generator = {
585   (void *) &srp_generator, sizeof (srp_generator)
586 };
587
588
589 /* Check if G and N are parameters from the SRP draft.
590  */
591 static int
592 check_g_n (const opaque * g, size_t n_g, const opaque * n, size_t n_n)
593 {
594
595   if (n_g != 1 || g[0] != srp_generator)
596     {
597       gnutls_assert ();
598       return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
599     }
600
601   if (n_n == sizeof (srp_params_1024) &&
602       memcmp (srp_params_1024, n, n_n) == 0)
603     {
604       return 0;
605     }
606
607   if (n_n == sizeof (srp_params_1536) &&
608       memcmp (srp_params_1536, n, n_n) == 0)
609     {
610       return 0;
611     }
612
613   if (n_n == sizeof (srp_params_2048) &&
614       memcmp (srp_params_2048, n, n_n) == 0)
615     {
616       return 0;
617     }
618
619   gnutls_assert ();
620   return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
621 }
622
623 /* Check if N is a prime and G a generator of the
624  * group. This is check only done if N is big enough.
625  * Otherwise only the included parameters must be used.
626  */
627 static int
628 group_check_g_n (gnutls_session_t session, bigint_t g, bigint_t n)
629 {
630   bigint_t q = NULL, two = NULL, w = NULL;
631   int ret;
632
633   if (_gnutls_mpi_get_nbits (n) < (session->internals.srp_prime_bits
634                                    ? session->internals.srp_prime_bits
635                                    : 2048))
636     {
637       gnutls_assert ();
638       return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
639     }
640
641   /* N must be of the form N=2q+1
642    * where q is also a prime.
643    */
644   if (_gnutls_prime_check (n) != 0)
645     {
646       _gnutls_mpi_log ("no prime N: ", n);
647       gnutls_assert ();
648       return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
649     }
650
651   two = _gnutls_mpi_new (4);
652   if (two == NULL)
653     {
654       gnutls_assert ();
655       return GNUTLS_E_MEMORY_ERROR;
656     }
657
658   q = _gnutls_mpi_alloc_like (n);
659   if (q == NULL)
660     {
661       gnutls_assert ();
662       ret = GNUTLS_E_MEMORY_ERROR;
663       goto error;
664     }
665
666   /* q = n-1 
667    */
668   _gnutls_mpi_sub_ui (q, n, 1);
669
670   /* q = q/2, remember that q is divisible by 2 (prime - 1)
671    */
672   _gnutls_mpi_set_ui (two, 2);
673   _gnutls_mpi_div (q, q, two);
674
675   if (_gnutls_prime_check (q) != 0)
676     {
677       /* N was not on the form N=2q+1, where q = prime
678        */
679       _gnutls_mpi_log ("no prime Q: ", q);
680       gnutls_assert ();
681       return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
682     }
683
684   /* We also check whether g is a generator,
685    */
686
687   /* check if g < q < N
688    */
689   if (_gnutls_mpi_cmp (g, q) >= 0)
690     {
691       gnutls_assert ();
692       ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
693       goto error;
694     }
695
696   w = _gnutls_mpi_alloc_like (q);
697   if (w == NULL)
698     {
699       gnutls_assert ();
700       ret = GNUTLS_E_MEMORY_ERROR;
701       goto error;
702     }
703
704   /* check if g^q mod N == N-1
705    * w = g^q mod N
706    */
707   _gnutls_mpi_powm (w, g, q, n);
708
709   /* w++
710    */
711   _gnutls_mpi_add_ui (w, w, 1);
712
713   if (_gnutls_mpi_cmp (w, n) != 0)
714     {
715       gnutls_assert ();
716       ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
717       goto error;
718     }
719
720   ret = 0;
721
722 error:
723   _gnutls_mpi_release (&q);
724   _gnutls_mpi_release (&two);
725   _gnutls_mpi_release (&w);
726
727   return ret;
728
729 }
730
731 /* receive the key exchange message ( n, g, s, B) 
732  */
733 int
734 _gnutls_proc_srp_server_kx (gnutls_session_t session, opaque * data,
735                             size_t _data_size)
736 {
737   uint8_t n_s;
738   uint16_t n_g, n_n, n_b;
739   size_t _n_g, _n_n, _n_b;
740   const uint8_t *data_n;
741   const uint8_t *data_g;
742   const uint8_t *data_s;
743   const uint8_t *data_b;
744   int i, ret;
745   opaque hd[SRP_MAX_HASH_SIZE];
746   char *username, *password;
747   ssize_t data_size = _data_size;
748   gnutls_srp_client_credentials_t cred;
749   extension_priv_data_t epriv;
750   srp_ext_st *priv;
751
752   ret = _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_SRP, &epriv);
753   if (ret < 0)
754     {
755       gnutls_assert ();
756       return GNUTLS_E_UNKNOWN_SRP_USERNAME;
757     }
758   priv = epriv.ptr;
759
760   cred = (gnutls_srp_client_credentials_t)
761     _gnutls_get_cred (session->key, GNUTLS_CRD_SRP, NULL);
762
763   if (cred == NULL)
764     {
765       gnutls_assert ();
766       return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
767     }
768
769   if (priv->username == NULL)
770     {
771       username = cred->username;
772       password = cred->password;
773     }
774   else
775     {
776       username = priv->username;
777       password = priv->password;
778     }
779
780   if (username == NULL || password == NULL)
781     {
782       gnutls_assert ();
783       return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
784     }
785
786   i = 0;
787
788   /* Read N 
789    */
790   DECR_LEN (data_size, 2);
791   n_n = _gnutls_read_uint16 (&data[i]);
792   i += 2;
793
794   DECR_LEN (data_size, n_n);
795   data_n = &data[i];
796   i += n_n;
797
798   /* Read G 
799    */
800   DECR_LEN (data_size, 2);
801   n_g = _gnutls_read_uint16 (&data[i]);
802   i += 2;
803
804   DECR_LEN (data_size, n_g);
805   data_g = &data[i];
806   i += n_g;
807
808   /* Read salt 
809    */
810   DECR_LEN (data_size, 1);
811   n_s = data[i];
812   i += 1;
813
814   DECR_LEN (data_size, n_s);
815   data_s = &data[i];
816   i += n_s;
817
818   /* Read B 
819    */
820   DECR_LEN (data_size, 2);
821   n_b = _gnutls_read_uint16 (&data[i]);
822   i += 2;
823
824   DECR_LEN (data_size, n_b);
825   data_b = &data[i];
826   i += n_b;
827
828   _n_g = n_g;
829   _n_n = n_n;
830   _n_b = n_b;
831
832   if (_gnutls_mpi_scan_nz (&N, data_n, _n_n) != 0)
833     {
834       gnutls_assert ();
835       return GNUTLS_E_MPI_SCAN_FAILED;
836     }
837
838   if (_gnutls_mpi_scan_nz (&G, data_g, _n_g) != 0)
839     {
840       gnutls_assert ();
841       return GNUTLS_E_MPI_SCAN_FAILED;
842     }
843
844   if (_gnutls_mpi_scan_nz (&B, data_b, _n_b) != 0)
845     {
846       gnutls_assert ();
847       return GNUTLS_E_MPI_SCAN_FAILED;
848     }
849
850
851   /* Check if the g and n are from the SRP
852    * draft. Otherwise check if N is a prime and G
853    * a generator.
854    */
855   if ((ret = check_g_n (data_g, _n_g, data_n, _n_n)) < 0)
856     {
857       _gnutls_x509_log ("Checking the SRP group parameters.\n");
858       if ((ret = group_check_g_n (session, G, N)) < 0)
859         {
860           gnutls_assert ();
861           return ret;
862         }
863     }
864
865   /* Checks if b % n == 0
866    */
867   if ((ret = check_b_mod_n (B, N)) < 0)
868     {
869       gnutls_assert ();
870       return ret;
871     }
872
873
874   /* generate x = SHA(s | SHA(U | ":" | p))
875    * (or the equivalent using bcrypt)
876    */
877   if ((ret =
878        _gnutls_calc_srp_x (username, password, (opaque *) data_s, n_s,
879                            &_n_g, hd)) < 0)
880     {
881       gnutls_assert ();
882       return ret;
883     }
884
885   if (_gnutls_mpi_scan_nz (&session->key->x, hd, _n_g) != 0)
886     {
887       gnutls_assert ();
888       return GNUTLS_E_MPI_SCAN_FAILED;
889     }
890
891
892   return i;                     /* return the processed data
893                                  * needed in auth_srp_rsa.
894                                  */
895 }
896
897 #endif /* ENABLE_SRP */