Corrected functionality of gnutls_record_get_direction(). Reported by Philip Allison.
[gnutls.git] / lib / auth_srp.c
blob724cbf030dd2003113b91ed5b54b0d2b4763c15c
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>
28 #ifdef ENABLE_SRP
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>
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,
50 NULL,
51 NULL, /* certificate */
52 _gnutls_proc_srp_server_kx,
53 _gnutls_proc_srp_client_kx,
54 NULL,
55 NULL
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
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.
72 inline static int
73 check_b_mod_n (bigint_t b, bigint_t n)
75 int ret;
76 bigint_t r;
78 r = _gnutls_mpi_mod (b, n);
80 if (r == NULL)
82 gnutls_assert ();
83 return GNUTLS_E_MEMORY_ERROR;
86 ret = _gnutls_mpi_cmp_ui (r, 0);
88 _gnutls_mpi_release (&r);
90 if (ret == 0)
92 gnutls_assert ();
93 return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
96 return 0;
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.
103 inline static int
104 check_a_mod_n (bigint_t a, bigint_t n)
106 int ret;
107 bigint_t r;
109 r = _gnutls_mpi_mod (a, n);
110 if (r == NULL)
112 gnutls_assert ();
113 return GNUTLS_E_MEMORY_ERROR;
116 ret = _gnutls_mpi_cmp_ui (r, 0);
118 _gnutls_mpi_release (&r);
120 if (ret == 0)
122 gnutls_assert ();
123 return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
126 return 0;
130 /* Send the first key exchange message ( g, n, s) and append the verifier algorithm number
131 * Data is allocated by the caller, and should have data_size size.
134 _gnutls_gen_srp_server_kx (gnutls_session_t session, opaque ** data)
136 int ret;
137 uint8_t *data_n, *data_s;
138 uint8_t *data_g;
139 char *username;
140 SRP_PWD_ENTRY *pwd_entry;
141 srp_server_auth_info_t info;
142 ssize_t data_size;
143 size_t n_b, tmp_size;
144 char buf[64];
145 uint8_t *data_b;
146 extension_priv_data_t epriv;
147 srp_ext_st *priv;
149 ret = _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_SRP, &epriv);
150 if (ret < 0) /* peer didn't send a username */
152 gnutls_assert ();
153 return GNUTLS_E_UNKNOWN_SRP_USERNAME;
155 priv = epriv.ptr;
157 if ((ret =
158 _gnutls_auth_info_set (session, GNUTLS_CRD_SRP,
159 sizeof (srp_server_auth_info_st), 1)) < 0)
161 gnutls_assert ();
162 return ret;
165 info = _gnutls_get_auth_info (session);
166 username = info->username;
168 _gnutls_str_cpy (username, MAX_USERNAME_SIZE, priv->username);
170 ret = _gnutls_srp_pwd_read_entry (session, username, &pwd_entry);
172 if (ret < 0)
174 gnutls_assert ();
175 return ret;
178 /* copy from pwd_entry to local variables (actually in session) */
179 tmp_size = pwd_entry->g.size;
180 if (_gnutls_mpi_scan_nz (&G, pwd_entry->g.data, tmp_size) < 0)
182 gnutls_assert ();
183 return GNUTLS_E_MPI_SCAN_FAILED;
186 tmp_size = pwd_entry->n.size;
187 if (_gnutls_mpi_scan_nz (&N, pwd_entry->n.data, tmp_size) < 0)
189 gnutls_assert ();
190 return GNUTLS_E_MPI_SCAN_FAILED;
193 tmp_size = pwd_entry->v.size;
194 if (_gnutls_mpi_scan_nz (&V, pwd_entry->v.data, tmp_size) < 0)
196 gnutls_assert ();
197 return GNUTLS_E_MPI_SCAN_FAILED;
200 /* Calculate: B = (k*v + g^b) % N
202 B = _gnutls_calc_srp_B (&_b, G, N, V);
203 if (B == NULL)
205 gnutls_assert ();
206 return GNUTLS_E_MEMORY_ERROR;
209 if (_gnutls_mpi_print (B, NULL, &n_b) != GNUTLS_E_SHORT_MEMORY_BUFFER)
211 gnutls_assert ();
212 return GNUTLS_E_MPI_PRINT_FAILED;
216 /* Allocate size to hold the N, g, s, B
219 data_size = (pwd_entry->n.size + 2 + pwd_entry->g.size + 2 +
220 pwd_entry->salt.size + 1) + (n_b + 2);
222 (*data) = gnutls_malloc (data_size);
223 if ((*data) == NULL)
225 gnutls_assert ();
226 return GNUTLS_E_MEMORY_ERROR;
229 /* copy N (mod n)
231 data_n = *data;
232 _gnutls_write_datum16 (data_n, pwd_entry->n);
235 /* copy G (generator) to data
237 data_g = &data_n[2 + pwd_entry->n.size];
238 _gnutls_write_datum16 (data_g, pwd_entry->g);
241 /* copy the salt
243 data_s = &data_g[2 + pwd_entry->g.size];
244 _gnutls_write_datum8 (data_s, pwd_entry->salt);
247 /* Copy the B value
250 data_b = &data_s[1 + pwd_entry->salt.size];
251 if (_gnutls_mpi_print (B, &data_b[2], &n_b) != 0)
253 gnutls_assert ();
254 return GNUTLS_E_MPI_PRINT_FAILED;
257 _gnutls_write_uint16 (n_b, data_b);
259 _gnutls_hard_log ("INT: SRP B[%d]: %s\n", (int) n_b,
260 _gnutls_bin2hex (&data_b[2], n_b, buf, sizeof (buf),
261 NULL));
263 _gnutls_srp_entry_free (pwd_entry);
265 return data_size;
268 /* return A = g^a % N */
270 _gnutls_gen_srp_client_kx (gnutls_session_t session, opaque ** data)
272 size_t n_a;
273 int ret;
274 uint8_t *data_a;
275 char *username, *password;
276 char buf[64];
277 gnutls_srp_client_credentials_t cred;
278 extension_priv_data_t epriv;
279 srp_ext_st *priv;
281 ret = _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_SRP, &epriv);
282 if (ret < 0) /* peer didn't send a username */
284 gnutls_assert ();
285 return GNUTLS_E_UNKNOWN_SRP_USERNAME;
287 priv = epriv.ptr;
289 cred = (gnutls_srp_client_credentials_t)
290 _gnutls_get_cred (session->key, GNUTLS_CRD_SRP, NULL);
292 if (cred == NULL)
294 gnutls_assert ();
295 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
298 if (priv->username == NULL)
300 username = cred->username;
301 password = cred->password;
303 else
306 username = priv->username;
307 password = priv->password;
310 if (username == NULL || password == NULL)
312 gnutls_assert ();
313 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
316 /* calc A = g^a % N
318 if (G == NULL || N == NULL)
320 gnutls_assert ();
321 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
324 A = _gnutls_calc_srp_A (&_a, G, N);
325 if (A == NULL)
327 gnutls_assert ();
328 return GNUTLS_E_MEMORY_ERROR;
331 /* Rest of SRP calculations
334 /* calculate u */
335 session->key->u = _gnutls_calc_srp_u (A, B, N);
336 if (session->key->u == NULL)
338 gnutls_assert ();
339 return GNUTLS_E_MEMORY_ERROR;
342 _gnutls_mpi_log ("SRP U: ", session->key->u);
344 /* S = (B - g^x) ^ (a + u * x) % N */
345 S = _gnutls_calc_srp_S2 (B, G, session->key->x, _a, session->key->u, N);
346 if (S == NULL)
348 gnutls_assert ();
349 return GNUTLS_E_MEMORY_ERROR;
352 _gnutls_mpi_log ("SRP B: ", B);
354 _gnutls_mpi_release (&_b);
355 _gnutls_mpi_release (&V);
356 _gnutls_mpi_release (&session->key->u);
357 _gnutls_mpi_release (&B);
359 ret = _gnutls_mpi_dprint (session->key->KEY, &session->key->key);
360 _gnutls_mpi_release (&S);
362 if (ret < 0)
364 gnutls_assert ();
365 return ret;
368 if (_gnutls_mpi_print (A, NULL, &n_a) != GNUTLS_E_SHORT_MEMORY_BUFFER)
370 gnutls_assert ();
371 return GNUTLS_E_MPI_PRINT_FAILED;
374 (*data) = gnutls_malloc (n_a + 2);
375 if ((*data) == NULL)
377 gnutls_assert ();
378 return GNUTLS_E_MEMORY_ERROR;
381 /* copy A */
382 data_a = (*data);
383 if (_gnutls_mpi_print (A, &data_a[2], &n_a) != 0)
385 gnutls_free (*data);
386 return GNUTLS_E_MPI_PRINT_FAILED;
389 _gnutls_hard_log ("INT: SRP A[%d]: %s\n", (int) n_a,
390 _gnutls_bin2hex (&data_a[2], n_a, buf, sizeof (buf),
391 NULL));
393 _gnutls_mpi_release (&A);
395 _gnutls_write_uint16 (n_a, data_a);
397 return n_a + 2;
401 /* just read A and put it to session */
403 _gnutls_proc_srp_client_kx (gnutls_session_t session, opaque * data,
404 size_t _data_size)
406 size_t _n_A;
407 ssize_t data_size = _data_size;
408 int ret;
410 DECR_LEN (data_size, 2);
411 _n_A = _gnutls_read_uint16 (&data[0]);
413 DECR_LEN (data_size, _n_A);
414 if (_gnutls_mpi_scan_nz (&A, &data[2], _n_A) || A == NULL)
416 gnutls_assert ();
417 return GNUTLS_E_MPI_SCAN_FAILED;
420 _gnutls_mpi_log ("SRP A: ", A);
421 _gnutls_mpi_log ("SRP B: ", B);
423 /* Checks if A % n == 0.
425 if ((ret = check_a_mod_n (A, N)) < 0)
427 gnutls_assert ();
428 return ret;
431 /* Start the SRP calculations.
432 * - Calculate u
434 session->key->u = _gnutls_calc_srp_u (A, B, N);
435 if (session->key->u == NULL)
437 gnutls_assert ();
438 return GNUTLS_E_MEMORY_ERROR;
441 _gnutls_mpi_log ("SRP U: ", session->key->u);
443 /* S = (A * v^u) ^ b % N
445 S = _gnutls_calc_srp_S1 (A, _b, session->key->u, V, N);
446 if (S == NULL)
448 gnutls_assert ();
449 return GNUTLS_E_MEMORY_ERROR;
452 _gnutls_mpi_log ("SRP S: ", S);
454 _gnutls_mpi_release (&A);
455 _gnutls_mpi_release (&_b);
456 _gnutls_mpi_release (&V);
457 _gnutls_mpi_release (&session->key->u);
458 _gnutls_mpi_release (&B);
460 ret = _gnutls_mpi_dprint (session->key->KEY, &session->key->key);
461 _gnutls_mpi_release (&S);
463 if (ret < 0)
465 gnutls_assert ();
466 return ret;
469 return 0;
474 /* Static parameters according to draft-ietf-tls-srp-07
475 * Note that if more parameters are added check_g_n()
476 * and _gnutls_srp_entry_free() should be changed.
478 static const unsigned char srp_params_1024[] = {
479 0xEE, 0xAF, 0x0A, 0xB9, 0xAD, 0xB3, 0x8D, 0xD6,
480 0x9C, 0x33, 0xF8, 0x0A, 0xFA, 0x8F, 0xC5, 0xE8,
481 0x60, 0x72, 0x61, 0x87, 0x75, 0xFF, 0x3C, 0x0B,
482 0x9E, 0xA2, 0x31, 0x4C, 0x9C, 0x25, 0x65, 0x76,
483 0xD6, 0x74, 0xDF, 0x74, 0x96, 0xEA, 0x81, 0xD3,
484 0x38, 0x3B, 0x48, 0x13, 0xD6, 0x92, 0xC6, 0xE0,
485 0xE0, 0xD5, 0xD8, 0xE2, 0x50, 0xB9, 0x8B, 0xE4,
486 0x8E, 0x49, 0x5C, 0x1D, 0x60, 0x89, 0xDA, 0xD1,
487 0x5D, 0xC7, 0xD7, 0xB4, 0x61, 0x54, 0xD6, 0xB6,
488 0xCE, 0x8E, 0xF4, 0xAD, 0x69, 0xB1, 0x5D, 0x49,
489 0x82, 0x55, 0x9B, 0x29, 0x7B, 0xCF, 0x18, 0x85,
490 0xC5, 0x29, 0xF5, 0x66, 0x66, 0x0E, 0x57, 0xEC,
491 0x68, 0xED, 0xBC, 0x3C, 0x05, 0x72, 0x6C, 0xC0,
492 0x2F, 0xD4, 0xCB, 0xF4, 0x97, 0x6E, 0xAA, 0x9A,
493 0xFD, 0x51, 0x38, 0xFE, 0x83, 0x76, 0x43, 0x5B,
494 0x9F, 0xC6, 0x1D, 0x2F, 0xC0, 0xEB, 0x06, 0xE3
497 static const unsigned char srp_generator = 0x02;
499 const gnutls_datum_t gnutls_srp_1024_group_prime = {
500 (void *) srp_params_1024, sizeof (srp_params_1024)
503 const gnutls_datum_t gnutls_srp_1024_group_generator = {
504 (void *) &srp_generator, sizeof (srp_generator)
507 static const unsigned char srp_params_1536[] = {
508 0x9D, 0xEF, 0x3C, 0xAF, 0xB9, 0x39, 0x27, 0x7A, 0xB1,
509 0xF1, 0x2A, 0x86, 0x17, 0xA4, 0x7B, 0xBB, 0xDB, 0xA5,
510 0x1D, 0xF4, 0x99, 0xAC, 0x4C, 0x80, 0xBE, 0xEE, 0xA9,
511 0x61, 0x4B, 0x19, 0xCC, 0x4D, 0x5F, 0x4F, 0x5F, 0x55,
512 0x6E, 0x27, 0xCB, 0xDE, 0x51, 0xC6, 0xA9, 0x4B, 0xE4,
513 0x60, 0x7A, 0x29, 0x15, 0x58, 0x90, 0x3B, 0xA0, 0xD0,
514 0xF8, 0x43, 0x80, 0xB6, 0x55, 0xBB, 0x9A, 0x22, 0xE8,
515 0xDC, 0xDF, 0x02, 0x8A, 0x7C, 0xEC, 0x67, 0xF0, 0xD0,
516 0x81, 0x34, 0xB1, 0xC8, 0xB9, 0x79, 0x89, 0x14, 0x9B,
517 0x60, 0x9E, 0x0B, 0xE3, 0xBA, 0xB6, 0x3D, 0x47, 0x54,
518 0x83, 0x81, 0xDB, 0xC5, 0xB1, 0xFC, 0x76, 0x4E, 0x3F,
519 0x4B, 0x53, 0xDD, 0x9D, 0xA1, 0x15, 0x8B, 0xFD, 0x3E,
520 0x2B, 0x9C, 0x8C, 0xF5, 0x6E, 0xDF, 0x01, 0x95, 0x39,
521 0x34, 0x96, 0x27, 0xDB, 0x2F, 0xD5, 0x3D, 0x24, 0xB7,
522 0xC4, 0x86, 0x65, 0x77, 0x2E, 0x43, 0x7D, 0x6C, 0x7F,
523 0x8C, 0xE4, 0x42, 0x73, 0x4A, 0xF7, 0xCC, 0xB7, 0xAE,
524 0x83, 0x7C, 0x26, 0x4A, 0xE3, 0xA9, 0xBE, 0xB8, 0x7F,
525 0x8A, 0x2F, 0xE9, 0xB8, 0xB5, 0x29, 0x2E, 0x5A, 0x02,
526 0x1F, 0xFF, 0x5E, 0x91, 0x47, 0x9E, 0x8C, 0xE7, 0xA2,
527 0x8C, 0x24, 0x42, 0xC6, 0xF3, 0x15, 0x18, 0x0F, 0x93,
528 0x49, 0x9A, 0x23, 0x4D, 0xCF, 0x76, 0xE3, 0xFE, 0xD1,
529 0x35, 0xF9, 0xBB
532 const gnutls_datum_t gnutls_srp_1536_group_prime = {
533 (void *) srp_params_1536, sizeof (srp_params_1536)
536 const gnutls_datum_t gnutls_srp_1536_group_generator = {
537 (void *) &srp_generator, sizeof (srp_generator)
540 static const unsigned char srp_params_2048[] = {
541 0xAC, 0x6B, 0xDB, 0x41, 0x32, 0x4A, 0x9A, 0x9B, 0xF1,
542 0x66, 0xDE, 0x5E, 0x13, 0x89, 0x58, 0x2F, 0xAF, 0x72,
543 0xB6, 0x65, 0x19, 0x87, 0xEE, 0x07, 0xFC, 0x31, 0x92,
544 0x94, 0x3D, 0xB5, 0x60, 0x50, 0xA3, 0x73, 0x29, 0xCB,
545 0xB4, 0xA0, 0x99, 0xED, 0x81, 0x93, 0xE0, 0x75, 0x77,
546 0x67, 0xA1, 0x3D, 0xD5, 0x23, 0x12, 0xAB, 0x4B, 0x03,
547 0x31, 0x0D, 0xCD, 0x7F, 0x48, 0xA9, 0xDA, 0x04, 0xFD,
548 0x50, 0xE8, 0x08, 0x39, 0x69, 0xED, 0xB7, 0x67, 0xB0,
549 0xCF, 0x60, 0x95, 0x17, 0x9A, 0x16, 0x3A, 0xB3, 0x66,
550 0x1A, 0x05, 0xFB, 0xD5, 0xFA, 0xAA, 0xE8, 0x29, 0x18,
551 0xA9, 0x96, 0x2F, 0x0B, 0x93, 0xB8, 0x55, 0xF9, 0x79,
552 0x93, 0xEC, 0x97, 0x5E, 0xEA, 0xA8, 0x0D, 0x74, 0x0A,
553 0xDB, 0xF4, 0xFF, 0x74, 0x73, 0x59, 0xD0, 0x41, 0xD5,
554 0xC3, 0x3E, 0xA7, 0x1D, 0x28, 0x1E, 0x44, 0x6B, 0x14,
555 0x77, 0x3B, 0xCA, 0x97, 0xB4, 0x3A, 0x23, 0xFB, 0x80,
556 0x16, 0x76, 0xBD, 0x20, 0x7A, 0x43, 0x6C, 0x64, 0x81,
557 0xF1, 0xD2, 0xB9, 0x07, 0x87, 0x17, 0x46, 0x1A, 0x5B,
558 0x9D, 0x32, 0xE6, 0x88, 0xF8, 0x77, 0x48, 0x54, 0x45,
559 0x23, 0xB5, 0x24, 0xB0, 0xD5, 0x7D, 0x5E, 0xA7, 0x7A,
560 0x27, 0x75, 0xD2, 0xEC, 0xFA, 0x03, 0x2C, 0xFB, 0xDB,
561 0xF5, 0x2F, 0xB3, 0x78, 0x61, 0x60, 0x27, 0x90, 0x04,
562 0xE5, 0x7A, 0xE6, 0xAF, 0x87, 0x4E, 0x73, 0x03, 0xCE,
563 0x53, 0x29, 0x9C, 0xCC, 0x04, 0x1C, 0x7B, 0xC3, 0x08,
564 0xD8, 0x2A, 0x56, 0x98, 0xF3, 0xA8, 0xD0, 0xC3, 0x82,
565 0x71, 0xAE, 0x35, 0xF8, 0xE9, 0xDB, 0xFB, 0xB6, 0x94,
566 0xB5, 0xC8, 0x03, 0xD8, 0x9F, 0x7A, 0xE4, 0x35, 0xDE,
567 0x23, 0x6D, 0x52, 0x5F, 0x54, 0x75, 0x9B, 0x65, 0xE3,
568 0x72, 0xFC, 0xD6, 0x8E, 0xF2, 0x0F, 0xA7, 0x11, 0x1F,
569 0x9E, 0x4A, 0xFF, 0x73
572 const gnutls_datum_t gnutls_srp_2048_group_prime = {
573 (void *) srp_params_2048, sizeof (srp_params_2048)
576 const gnutls_datum_t gnutls_srp_2048_group_generator = {
577 (void *) &srp_generator, sizeof (srp_generator)
581 /* Check if G and N are parameters from the SRP draft.
583 static int
584 check_g_n (const opaque * g, size_t n_g, const opaque * n, size_t n_n)
587 if (n_g != 1 || g[0] != srp_generator)
589 gnutls_assert ();
590 return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
593 if (n_n == sizeof (srp_params_1024) &&
594 memcmp (srp_params_1024, n, n_n) == 0)
596 return 0;
599 if (n_n == sizeof (srp_params_1536) &&
600 memcmp (srp_params_1536, n, n_n) == 0)
602 return 0;
605 if (n_n == sizeof (srp_params_2048) &&
606 memcmp (srp_params_2048, n, n_n) == 0)
608 return 0;
611 gnutls_assert ();
612 return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
615 /* Check if N is a prime and G a generator of the
616 * group. This is check only done if N is big enough.
617 * Otherwise only the included parameters must be used.
619 static int
620 group_check_g_n (gnutls_session_t session, bigint_t g, bigint_t n)
622 bigint_t q = NULL, two = NULL, w = NULL;
623 int ret;
625 if (_gnutls_mpi_get_nbits (n) < (session->internals.srp_prime_bits
626 ? session->internals.srp_prime_bits
627 : 2048))
629 gnutls_assert ();
630 return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
633 /* N must be of the form N=2q+1
634 * where q is also a prime.
636 if (_gnutls_prime_check (n) != 0)
638 _gnutls_mpi_log ("no prime N: ", n);
639 gnutls_assert ();
640 return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
643 two = _gnutls_mpi_new (4);
644 if (two == NULL)
646 gnutls_assert ();
647 return GNUTLS_E_MEMORY_ERROR;
650 q = _gnutls_mpi_alloc_like (n);
651 if (q == NULL)
653 gnutls_assert ();
654 ret = GNUTLS_E_MEMORY_ERROR;
655 goto error;
658 /* q = n-1
660 _gnutls_mpi_sub_ui (q, n, 1);
662 /* q = q/2, remember that q is divisible by 2 (prime - 1)
664 _gnutls_mpi_set_ui (two, 2);
665 _gnutls_mpi_div (q, q, two);
667 if (_gnutls_prime_check (q) != 0)
669 /* N was not on the form N=2q+1, where q = prime
671 _gnutls_mpi_log ("no prime Q: ", q);
672 gnutls_assert ();
673 return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
676 /* We also check whether g is a generator,
679 /* check if g < q < N
681 if (_gnutls_mpi_cmp (g, q) >= 0)
683 gnutls_assert ();
684 ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
685 goto error;
688 w = _gnutls_mpi_alloc_like (q);
689 if (w == NULL)
691 gnutls_assert ();
692 ret = GNUTLS_E_MEMORY_ERROR;
693 goto error;
696 /* check if g^q mod N == N-1
697 * w = g^q mod N
699 _gnutls_mpi_powm (w, g, q, n);
701 /* w++
703 _gnutls_mpi_add_ui (w, w, 1);
705 if (_gnutls_mpi_cmp (w, n) != 0)
707 gnutls_assert ();
708 ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
709 goto error;
712 ret = 0;
714 error:
715 _gnutls_mpi_release (&q);
716 _gnutls_mpi_release (&two);
717 _gnutls_mpi_release (&w);
719 return ret;
723 /* receive the key exchange message ( n, g, s, B)
726 _gnutls_proc_srp_server_kx (gnutls_session_t session, opaque * data,
727 size_t _data_size)
729 uint8_t n_s;
730 uint16_t n_g, n_n, n_b;
731 size_t _n_g, _n_n, _n_b;
732 const uint8_t *data_n;
733 const uint8_t *data_g;
734 const uint8_t *data_s;
735 const uint8_t *data_b;
736 int i, ret;
737 opaque hd[SRP_MAX_HASH_SIZE];
738 char *username, *password;
739 ssize_t data_size = _data_size;
740 gnutls_srp_client_credentials_t cred;
741 extension_priv_data_t epriv;
742 srp_ext_st *priv;
744 ret = _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_SRP, &epriv);
745 if (ret < 0)
747 gnutls_assert ();
748 return GNUTLS_E_UNKNOWN_SRP_USERNAME;
750 priv = epriv.ptr;
752 cred = (gnutls_srp_client_credentials_t)
753 _gnutls_get_cred (session->key, GNUTLS_CRD_SRP, NULL);
755 if (cred == NULL)
757 gnutls_assert ();
758 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
761 if (priv->username == NULL)
763 username = cred->username;
764 password = cred->password;
766 else
768 username = priv->username;
769 password = priv->password;
772 if (username == NULL || password == NULL)
774 gnutls_assert ();
775 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
778 i = 0;
780 /* Read N
782 DECR_LEN (data_size, 2);
783 n_n = _gnutls_read_uint16 (&data[i]);
784 i += 2;
786 DECR_LEN (data_size, n_n);
787 data_n = &data[i];
788 i += n_n;
790 /* Read G
792 DECR_LEN (data_size, 2);
793 n_g = _gnutls_read_uint16 (&data[i]);
794 i += 2;
796 DECR_LEN (data_size, n_g);
797 data_g = &data[i];
798 i += n_g;
800 /* Read salt
802 DECR_LEN (data_size, 1);
803 n_s = data[i];
804 i += 1;
806 DECR_LEN (data_size, n_s);
807 data_s = &data[i];
808 i += n_s;
810 /* Read B
812 DECR_LEN (data_size, 2);
813 n_b = _gnutls_read_uint16 (&data[i]);
814 i += 2;
816 DECR_LEN (data_size, n_b);
817 data_b = &data[i];
818 i += n_b;
820 _n_g = n_g;
821 _n_n = n_n;
822 _n_b = n_b;
824 if (_gnutls_mpi_scan_nz (&N, data_n, _n_n) != 0)
826 gnutls_assert ();
827 return GNUTLS_E_MPI_SCAN_FAILED;
830 if (_gnutls_mpi_scan_nz (&G, data_g, _n_g) != 0)
832 gnutls_assert ();
833 return GNUTLS_E_MPI_SCAN_FAILED;
836 if (_gnutls_mpi_scan_nz (&B, data_b, _n_b) != 0)
838 gnutls_assert ();
839 return GNUTLS_E_MPI_SCAN_FAILED;
843 /* Check if the g and n are from the SRP
844 * draft. Otherwise check if N is a prime and G
845 * a generator.
847 if ((ret = check_g_n (data_g, _n_g, data_n, _n_n)) < 0)
849 _gnutls_x509_log ("Checking the SRP group parameters.\n");
850 if ((ret = group_check_g_n (session, G, N)) < 0)
852 gnutls_assert ();
853 return ret;
857 /* Checks if b % n == 0
859 if ((ret = check_b_mod_n (B, N)) < 0)
861 gnutls_assert ();
862 return ret;
866 /* generate x = SHA(s | SHA(U | ":" | p))
867 * (or the equivalent using bcrypt)
869 if ((ret =
870 _gnutls_calc_srp_x (username, password, (opaque *) data_s, n_s,
871 &_n_g, hd)) < 0)
873 gnutls_assert ();
874 return ret;
877 if (_gnutls_mpi_scan_nz (&session->key->x, hd, _n_g) != 0)
879 gnutls_assert ();
880 return GNUTLS_E_MPI_SCAN_FAILED;
884 return i; /* return the processed data
885 * needed in auth_srp_rsa.
889 #endif /* ENABLE_SRP */