Check whether `-fgnu89-inline' is supported before using it.
[gnutls.git] / lib / auth_srp.c
blob4f2a5d7db2c170ed70ab5325616b36f48a4b2d45
1 /*
2 * Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation
4 * Author: Nikos Mavrogiannopoulos
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,
21 * USA
25 #include <gnutls_int.h>
27 #ifdef ENABLE_SRP
29 #include "gnutls_errors.h"
30 #include "auth_srp_passwd.h"
31 #include "gnutls_auth.h"
32 #include "gnutls_auth_int.h"
33 #include "gnutls_srp.h"
34 #include "debug.h"
35 #include "gnutls_num.h"
36 #include "auth_srp.h"
37 #include <gnutls_str.h>
38 #include <gnutls_datum.h>
40 int _gnutls_gen_srp_server_kx (gnutls_session_t, opaque **);
41 int _gnutls_gen_srp_client_kx (gnutls_session_t, opaque **);
43 int _gnutls_proc_srp_server_kx (gnutls_session_t, opaque *, size_t);
44 int _gnutls_proc_srp_client_kx (gnutls_session_t, opaque *, size_t);
46 const mod_auth_st srp_auth_struct = {
47 "SRP",
48 NULL,
49 NULL,
50 _gnutls_gen_srp_server_kx,
51 _gnutls_gen_srp_client_kx,
52 NULL,
53 NULL,
55 NULL,
56 NULL, /* certificate */
57 _gnutls_proc_srp_server_kx,
58 _gnutls_proc_srp_client_kx,
59 NULL,
60 NULL
64 #define _b session->key->b
65 #define B session->key->B
66 #define _a session->key->a
67 #define A session->key->A
68 #define N session->key->client_p
69 #define G session->key->client_g
70 #define V session->key->x
71 #define S session->key->KEY
73 /* Checks if b%n==0 which is a fatal srp error.
74 * Returns a proper error code in that case, and 0 when
75 * all are ok.
77 inline static int
78 check_b_mod_n (mpi_t b, mpi_t n)
80 int ret;
81 mpi_t r = _gnutls_mpi_alloc_like (b);
83 if (r == NULL)
85 gnutls_assert ();
86 return GNUTLS_E_MEMORY_ERROR;
89 _gnutls_mpi_mod (r, b, n);
90 ret = _gnutls_mpi_cmp_ui (r, 0);
92 _gnutls_mpi_release (&r);
94 if (ret == 0)
96 gnutls_assert ();
97 return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
100 return 0;
103 /* Checks if a%n==0,+1,-1%n which is a fatal srp error.
104 * Returns a proper error code in that case, and 0 when
105 * all are ok.
107 inline static int
108 check_a_mod_n (mpi_t a, mpi_t n)
110 int ret;
111 mpi_t r = _gnutls_mpi_alloc_like (a);
113 if (r == NULL)
115 gnutls_assert ();
116 return GNUTLS_E_MEMORY_ERROR;
119 _gnutls_mpi_mod (r, a, n);
120 ret = _gnutls_mpi_cmp_ui (r, 0);
122 _gnutls_mpi_release (&r);
124 if (ret == 0)
126 gnutls_assert ();
127 return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
130 return 0;
134 /* Send the first key exchange message ( g, n, s) and append the verifier algorithm number
135 * Data is allocated by the caller, and should have data_size size.
138 _gnutls_gen_srp_server_kx (gnutls_session_t session, opaque ** data)
140 int ret;
141 uint8_t *data_n, *data_s;
142 uint8_t *data_g;
143 char *username;
144 SRP_PWD_ENTRY *pwd_entry;
145 srp_server_auth_info_t info;
146 ssize_t data_size;
147 size_t n_b, tmp_size;
148 char buf[64];
149 uint8_t *data_b;
151 if ((ret =
152 _gnutls_auth_info_set (session, GNUTLS_CRD_SRP,
153 sizeof (srp_server_auth_info_st), 1)) < 0)
155 gnutls_assert ();
156 return ret;
159 info = _gnutls_get_auth_info (session);
160 username = info->username;
162 _gnutls_str_cpy (username, MAX_SRP_USERNAME,
163 session->security_parameters.extensions.srp_username);
165 ret = _gnutls_srp_pwd_read_entry (session, username, &pwd_entry);
167 if (ret < 0)
169 gnutls_assert ();
170 return ret;
173 /* copy from pwd_entry to local variables (actually in session) */
174 tmp_size = pwd_entry->g.size;
175 if (_gnutls_mpi_scan_nz (&G, pwd_entry->g.data, &tmp_size) < 0)
177 gnutls_assert ();
178 return GNUTLS_E_MPI_SCAN_FAILED;
181 tmp_size = pwd_entry->n.size;
182 if (_gnutls_mpi_scan_nz (&N, pwd_entry->n.data, &tmp_size) < 0)
184 gnutls_assert ();
185 return GNUTLS_E_MPI_SCAN_FAILED;
188 tmp_size = pwd_entry->v.size;
189 if (_gnutls_mpi_scan_nz (&V, pwd_entry->v.data, &tmp_size) < 0)
191 gnutls_assert ();
192 return GNUTLS_E_MPI_SCAN_FAILED;
195 /* Calculate: B = (k*v + g^b) % N
197 B = _gnutls_calc_srp_B (&_b, G, N, V);
198 if (B == NULL)
200 gnutls_assert ();
201 return GNUTLS_E_MEMORY_ERROR;
204 if (_gnutls_mpi_print (NULL, &n_b, B) != 0)
206 gnutls_assert ();
207 return GNUTLS_E_MPI_PRINT_FAILED;
211 /* Allocate size to hold the N, g, s, B
214 data_size = (pwd_entry->n.size + 2 + pwd_entry->g.size + 2 +
215 pwd_entry->salt.size + 1) + (n_b + 2);
217 (*data) = gnutls_malloc (data_size);
218 if ((*data) == NULL)
220 gnutls_assert ();
221 return GNUTLS_E_MEMORY_ERROR;
224 /* copy N (mod n)
226 data_n = *data;
227 _gnutls_write_datum16 (data_n, pwd_entry->n);
230 /* copy G (generator) to data
232 data_g = &data_n[2 + pwd_entry->n.size];
233 _gnutls_write_datum16 (data_g, pwd_entry->g);
236 /* copy the salt
238 data_s = &data_g[2 + pwd_entry->g.size];
239 _gnutls_write_datum8 (data_s, pwd_entry->salt);
242 /* Copy the B value
245 data_b = &data_s[1 + pwd_entry->salt.size];
246 if (_gnutls_mpi_print (&data_b[2], &n_b, B) != 0)
248 gnutls_assert();
249 return GNUTLS_E_MPI_PRINT_FAILED;
252 _gnutls_write_uint16 (n_b, data_b);
254 _gnutls_hard_log ("INT: SRP B[%d]: %s\n", n_b,
255 _gnutls_bin2hex (&data_b[2], n_b, buf, sizeof (buf)));
257 _gnutls_srp_entry_free (pwd_entry);
259 return data_size;
262 /* return A = g^a % N */
264 _gnutls_gen_srp_client_kx (gnutls_session_t session, opaque ** data)
266 size_t n_a;
267 int ret;
268 uint8_t *data_a;
269 char *username, *password;
270 char buf[64];
271 gnutls_srp_client_credentials_t cred;
274 cred = (gnutls_srp_client_credentials_t)
275 _gnutls_get_cred (session->key, GNUTLS_CRD_SRP, NULL);
277 if (cred == NULL)
279 gnutls_assert ();
280 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
283 if (session->internals.srp_username == NULL)
285 username = cred->username;
286 password = cred->password;
288 else
290 username = session->internals.srp_username;
291 password = session->internals.srp_password;
294 if (username == NULL || password == NULL)
296 gnutls_assert ();
297 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
300 /* calc A = g^a % N
302 if (G == NULL || N == NULL)
304 gnutls_assert ();
305 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
308 A = _gnutls_calc_srp_A (&_a, G, N);
309 if (A == NULL)
311 gnutls_assert ();
312 return GNUTLS_E_MEMORY_ERROR;
315 /* Rest of SRP calculations
318 /* calculate u */
319 session->key->u = _gnutls_calc_srp_u (A, B, N);
320 if (session->key->u == NULL)
322 gnutls_assert ();
323 return GNUTLS_E_MEMORY_ERROR;
326 _gnutls_dump_mpi ("SRP U: ", session->key->u);
328 /* S = (B - g^x) ^ (a + u * x) % N */
329 S = _gnutls_calc_srp_S2 (B, G, session->key->x, _a, session->key->u, N);
330 if (S == NULL)
332 gnutls_assert ();
333 return GNUTLS_E_MEMORY_ERROR;
336 _gnutls_dump_mpi ("SRP B: ", B);
338 _gnutls_mpi_release (&_b);
339 _gnutls_mpi_release (&V);
340 _gnutls_mpi_release (&session->key->u);
341 _gnutls_mpi_release (&B);
343 ret = _gnutls_mpi_dprint (&session->key->key, session->key->KEY);
344 _gnutls_mpi_release (&S);
346 if (ret < 0)
348 gnutls_assert();
349 return ret;
352 if (_gnutls_mpi_print (NULL, &n_a, A) != 0)
354 gnutls_assert ();
355 return GNUTLS_E_MPI_PRINT_FAILED;
358 (*data) = gnutls_malloc (n_a + 2);
359 if ((*data) == NULL)
361 gnutls_assert ();
362 return GNUTLS_E_MEMORY_ERROR;
365 /* copy A */
366 data_a = (*data);
367 if (_gnutls_mpi_print (&data_a[2], &n_a, A) != 0)
369 gnutls_free (*data);
370 return GNUTLS_E_MPI_PRINT_FAILED;
373 _gnutls_hard_log ("INT: SRP A[%d]: %s\n", n_a,
374 _gnutls_bin2hex (&data_a[2], n_a, buf, sizeof (buf)));
376 _gnutls_mpi_release (&A);
378 _gnutls_write_uint16 (n_a, data_a);
380 return n_a + 2;
384 /* just read A and put it to session */
386 _gnutls_proc_srp_client_kx (gnutls_session_t session, opaque * data,
387 size_t _data_size)
389 size_t _n_A;
390 ssize_t data_size = _data_size;
391 int ret;
393 DECR_LEN (data_size, 2);
394 _n_A = _gnutls_read_uint16 (&data[0]);
396 DECR_LEN (data_size, _n_A);
397 if (_gnutls_mpi_scan_nz (&A, &data[2], &_n_A) || A == NULL)
399 gnutls_assert ();
400 return GNUTLS_E_MPI_SCAN_FAILED;
403 _gnutls_dump_mpi ("SRP A: ", A);
404 _gnutls_dump_mpi ("SRP B: ", B);
406 /* Checks if A % n == 0.
408 if ((ret = check_a_mod_n (A, N)) < 0)
410 gnutls_assert ();
411 return ret;
414 /* Start the SRP calculations.
415 * - Calculate u
417 session->key->u = _gnutls_calc_srp_u (A, B, N);
418 if (session->key->u == NULL)
420 gnutls_assert ();
421 return GNUTLS_E_MEMORY_ERROR;
424 _gnutls_dump_mpi ("SRP U: ", session->key->u);
426 /* S = (A * v^u) ^ b % N
428 S = _gnutls_calc_srp_S1 (A, _b, session->key->u, V, N);
429 if (S == NULL)
431 gnutls_assert ();
432 return GNUTLS_E_MEMORY_ERROR;
435 _gnutls_dump_mpi ("SRP S: ", S);
437 _gnutls_mpi_release (&A);
438 _gnutls_mpi_release (&_b);
439 _gnutls_mpi_release (&V);
440 _gnutls_mpi_release (&session->key->u);
441 _gnutls_mpi_release (&B);
443 ret = _gnutls_mpi_dprint (&session->key->key, session->key->KEY);
444 _gnutls_mpi_release (&S);
446 if (ret < 0)
448 gnutls_assert ();
449 return ret;
452 return 0;
457 /* Static parameters according to draft-ietf-tls-srp-07
458 * Note that if more parameters are added check_g_n()
459 * and _gnutls_srp_entry_free() should be changed.
461 static const unsigned char srp_params_1024[] = {
462 0xEE, 0xAF, 0x0A, 0xB9, 0xAD, 0xB3, 0x8D, 0xD6,
463 0x9C, 0x33, 0xF8, 0x0A, 0xFA, 0x8F, 0xC5, 0xE8,
464 0x60, 0x72, 0x61, 0x87, 0x75, 0xFF, 0x3C, 0x0B,
465 0x9E, 0xA2, 0x31, 0x4C, 0x9C, 0x25, 0x65, 0x76,
466 0xD6, 0x74, 0xDF, 0x74, 0x96, 0xEA, 0x81, 0xD3,
467 0x38, 0x3B, 0x48, 0x13, 0xD6, 0x92, 0xC6, 0xE0,
468 0xE0, 0xD5, 0xD8, 0xE2, 0x50, 0xB9, 0x8B, 0xE4,
469 0x8E, 0x49, 0x5C, 0x1D, 0x60, 0x89, 0xDA, 0xD1,
470 0x5D, 0xC7, 0xD7, 0xB4, 0x61, 0x54, 0xD6, 0xB6,
471 0xCE, 0x8E, 0xF4, 0xAD, 0x69, 0xB1, 0x5D, 0x49,
472 0x82, 0x55, 0x9B, 0x29, 0x7B, 0xCF, 0x18, 0x85,
473 0xC5, 0x29, 0xF5, 0x66, 0x66, 0x0E, 0x57, 0xEC,
474 0x68, 0xED, 0xBC, 0x3C, 0x05, 0x72, 0x6C, 0xC0,
475 0x2F, 0xD4, 0xCB, 0xF4, 0x97, 0x6E, 0xAA, 0x9A,
476 0xFD, 0x51, 0x38, 0xFE, 0x83, 0x76, 0x43, 0x5B,
477 0x9F, 0xC6, 0x1D, 0x2F, 0xC0, 0xEB, 0x06, 0xE3
480 static const unsigned char srp_generator = 0x02;
482 const gnutls_datum_t gnutls_srp_1024_group_prime = {
483 (void *) srp_params_1024, sizeof (srp_params_1024)
485 const gnutls_datum_t gnutls_srp_1024_group_generator = {
486 (void *) &srp_generator, sizeof (srp_generator)
489 static const unsigned char srp_params_1536[] = {
490 0x9D, 0xEF, 0x3C, 0xAF, 0xB9, 0x39, 0x27, 0x7A, 0xB1,
491 0xF1, 0x2A, 0x86, 0x17, 0xA4, 0x7B, 0xBB, 0xDB, 0xA5,
492 0x1D, 0xF4, 0x99, 0xAC, 0x4C, 0x80, 0xBE, 0xEE, 0xA9,
493 0x61, 0x4B, 0x19, 0xCC, 0x4D, 0x5F, 0x4F, 0x5F, 0x55,
494 0x6E, 0x27, 0xCB, 0xDE, 0x51, 0xC6, 0xA9, 0x4B, 0xE4,
495 0x60, 0x7A, 0x29, 0x15, 0x58, 0x90, 0x3B, 0xA0, 0xD0,
496 0xF8, 0x43, 0x80, 0xB6, 0x55, 0xBB, 0x9A, 0x22, 0xE8,
497 0xDC, 0xDF, 0x02, 0x8A, 0x7C, 0xEC, 0x67, 0xF0, 0xD0,
498 0x81, 0x34, 0xB1, 0xC8, 0xB9, 0x79, 0x89, 0x14, 0x9B,
499 0x60, 0x9E, 0x0B, 0xE3, 0xBA, 0xB6, 0x3D, 0x47, 0x54,
500 0x83, 0x81, 0xDB, 0xC5, 0xB1, 0xFC, 0x76, 0x4E, 0x3F,
501 0x4B, 0x53, 0xDD, 0x9D, 0xA1, 0x15, 0x8B, 0xFD, 0x3E,
502 0x2B, 0x9C, 0x8C, 0xF5, 0x6E, 0xDF, 0x01, 0x95, 0x39,
503 0x34, 0x96, 0x27, 0xDB, 0x2F, 0xD5, 0x3D, 0x24, 0xB7,
504 0xC4, 0x86, 0x65, 0x77, 0x2E, 0x43, 0x7D, 0x6C, 0x7F,
505 0x8C, 0xE4, 0x42, 0x73, 0x4A, 0xF7, 0xCC, 0xB7, 0xAE,
506 0x83, 0x7C, 0x26, 0x4A, 0xE3, 0xA9, 0xBE, 0xB8, 0x7F,
507 0x8A, 0x2F, 0xE9, 0xB8, 0xB5, 0x29, 0x2E, 0x5A, 0x02,
508 0x1F, 0xFF, 0x5E, 0x91, 0x47, 0x9E, 0x8C, 0xE7, 0xA2,
509 0x8C, 0x24, 0x42, 0xC6, 0xF3, 0x15, 0x18, 0x0F, 0x93,
510 0x49, 0x9A, 0x23, 0x4D, 0xCF, 0x76, 0xE3, 0xFE, 0xD1,
511 0x35, 0xF9, 0xBB
514 const gnutls_datum_t gnutls_srp_1536_group_prime = {
515 (void *) srp_params_1536, sizeof (srp_params_1536)
517 const gnutls_datum_t gnutls_srp_1536_group_generator = {
518 (void *) &srp_generator, sizeof (srp_generator)
521 static const unsigned char srp_params_2048[] = {
522 0xAC, 0x6B, 0xDB, 0x41, 0x32, 0x4A, 0x9A, 0x9B, 0xF1,
523 0x66, 0xDE, 0x5E, 0x13, 0x89, 0x58, 0x2F, 0xAF, 0x72,
524 0xB6, 0x65, 0x19, 0x87, 0xEE, 0x07, 0xFC, 0x31, 0x92,
525 0x94, 0x3D, 0xB5, 0x60, 0x50, 0xA3, 0x73, 0x29, 0xCB,
526 0xB4, 0xA0, 0x99, 0xED, 0x81, 0x93, 0xE0, 0x75, 0x77,
527 0x67, 0xA1, 0x3D, 0xD5, 0x23, 0x12, 0xAB, 0x4B, 0x03,
528 0x31, 0x0D, 0xCD, 0x7F, 0x48, 0xA9, 0xDA, 0x04, 0xFD,
529 0x50, 0xE8, 0x08, 0x39, 0x69, 0xED, 0xB7, 0x67, 0xB0,
530 0xCF, 0x60, 0x95, 0x17, 0x9A, 0x16, 0x3A, 0xB3, 0x66,
531 0x1A, 0x05, 0xFB, 0xD5, 0xFA, 0xAA, 0xE8, 0x29, 0x18,
532 0xA9, 0x96, 0x2F, 0x0B, 0x93, 0xB8, 0x55, 0xF9, 0x79,
533 0x93, 0xEC, 0x97, 0x5E, 0xEA, 0xA8, 0x0D, 0x74, 0x0A,
534 0xDB, 0xF4, 0xFF, 0x74, 0x73, 0x59, 0xD0, 0x41, 0xD5,
535 0xC3, 0x3E, 0xA7, 0x1D, 0x28, 0x1E, 0x44, 0x6B, 0x14,
536 0x77, 0x3B, 0xCA, 0x97, 0xB4, 0x3A, 0x23, 0xFB, 0x80,
537 0x16, 0x76, 0xBD, 0x20, 0x7A, 0x43, 0x6C, 0x64, 0x81,
538 0xF1, 0xD2, 0xB9, 0x07, 0x87, 0x17, 0x46, 0x1A, 0x5B,
539 0x9D, 0x32, 0xE6, 0x88, 0xF8, 0x77, 0x48, 0x54, 0x45,
540 0x23, 0xB5, 0x24, 0xB0, 0xD5, 0x7D, 0x5E, 0xA7, 0x7A,
541 0x27, 0x75, 0xD2, 0xEC, 0xFA, 0x03, 0x2C, 0xFB, 0xDB,
542 0xF5, 0x2F, 0xB3, 0x78, 0x61, 0x60, 0x27, 0x90, 0x04,
543 0xE5, 0x7A, 0xE6, 0xAF, 0x87, 0x4E, 0x73, 0x03, 0xCE,
544 0x53, 0x29, 0x9C, 0xCC, 0x04, 0x1C, 0x7B, 0xC3, 0x08,
545 0xD8, 0x2A, 0x56, 0x98, 0xF3, 0xA8, 0xD0, 0xC3, 0x82,
546 0x71, 0xAE, 0x35, 0xF8, 0xE9, 0xDB, 0xFB, 0xB6, 0x94,
547 0xB5, 0xC8, 0x03, 0xD8, 0x9F, 0x7A, 0xE4, 0x35, 0xDE,
548 0x23, 0x6D, 0x52, 0x5F, 0x54, 0x75, 0x9B, 0x65, 0xE3,
549 0x72, 0xFC, 0xD6, 0x8E, 0xF2, 0x0F, 0xA7, 0x11, 0x1F,
550 0x9E, 0x4A, 0xFF, 0x73
553 const gnutls_datum_t gnutls_srp_2048_group_prime = {
554 (void *) srp_params_2048, sizeof (srp_params_2048)
556 const gnutls_datum_t gnutls_srp_2048_group_generator = {
557 (void *) &srp_generator, sizeof (srp_generator)
561 /* Check if G and N are parameters from the SRP draft.
563 static int
564 check_g_n (const opaque * g, size_t n_g, const opaque * n, size_t n_n)
567 if (n_g != 1 || g[0] != srp_generator)
569 gnutls_assert();
570 return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
573 if (n_n == sizeof (srp_params_1024) &&
574 memcmp (srp_params_1024, n, n_n) == 0)
576 return 0;
579 if (n_n == sizeof (srp_params_1536) &&
580 memcmp (srp_params_1536, n, n_n) == 0)
582 return 0;
585 if (n_n == sizeof (srp_params_2048) &&
586 memcmp (srp_params_2048, n, n_n) == 0)
588 return 0;
591 gnutls_assert();
592 return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
595 /* Check if N is a prime and G a generator of the
596 * group. This is check only done if N is big enough.
597 * Otherwise only the included parameters must be used.
599 static int
600 group_check_g_n (mpi_t g, mpi_t n)
602 mpi_t q = NULL, two = NULL, w = NULL;
603 int ret;
605 if (_gnutls_mpi_get_nbits (n) < 2048)
607 gnutls_assert ();
608 return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
611 /* N must be of the form N=2q+1
612 * where q is also a prime.
614 if (_gnutls_prime_check (n, 0) != 0)
616 _gnutls_dump_mpi ("no prime N: ", n);
617 gnutls_assert ();
618 return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
621 two = _gnutls_mpi_new (4);
622 if (two == NULL)
624 gnutls_assert ();
625 return GNUTLS_E_MEMORY_ERROR;
628 q = _gnutls_mpi_alloc_like (n);
629 if (q == NULL)
631 gnutls_assert ();
632 ret = GNUTLS_E_MEMORY_ERROR;
633 goto error;
636 /* q = n-1
638 _gnutls_mpi_sub_ui (q, n, 1);
640 /* q = q/2, remember that q is divisible by 2 (prime - 1)
642 _gnutls_mpi_set_ui (two, 2);
643 _gnutls_mpi_div (q, NULL, q, two, 0);
645 if (_gnutls_prime_check (q, 0) != 0)
647 /* N was not on the form N=2q+1, where q = prime
649 _gnutls_dump_mpi ("no prime Q: ", q);
650 gnutls_assert ();
651 return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
654 /* We also check whether g is a generator,
657 /* check if g < q < N
659 if (_gnutls_mpi_cmp (g, q) >= 0)
661 gnutls_assert ();
662 ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
663 goto error;
666 w = _gnutls_mpi_alloc_like (q);
667 if (w == NULL)
669 gnutls_assert ();
670 ret = GNUTLS_E_MEMORY_ERROR;
671 goto error;
674 /* check if g^q mod N == N-1
675 * w = g^q mod N
677 _gnutls_mpi_powm (w, g, q, n);
679 /* w++
681 _gnutls_mpi_add_ui (w, w, 1);
683 if (_gnutls_mpi_cmp (w, n) != 0)
685 gnutls_assert ();
686 ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
687 goto error;
690 ret = 0;
692 error:
693 _gnutls_mpi_release (&q);
694 _gnutls_mpi_release (&two);
695 _gnutls_mpi_release (&w);
697 return ret;
701 /* receive the key exchange message ( n, g, s, B)
704 _gnutls_proc_srp_server_kx (gnutls_session_t session, opaque * data,
705 size_t _data_size)
707 uint8_t n_s;
708 uint16_t n_g, n_n, n_b;
709 size_t _n_s, _n_g, _n_n, _n_b;
710 const uint8_t *data_n;
711 const uint8_t *data_g;
712 const uint8_t *data_s;
713 const uint8_t *data_b;
714 int i, ret;
715 opaque hd[SRP_MAX_HASH_SIZE];
716 char *username, *password;
717 ssize_t data_size = _data_size;
718 gnutls_srp_client_credentials_t cred;
720 cred = (gnutls_srp_client_credentials_t)
721 _gnutls_get_cred (session->key, GNUTLS_CRD_SRP, NULL);
723 if (cred == NULL)
725 gnutls_assert ();
726 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
729 if (session->internals.srp_username == NULL)
731 username = cred->username;
732 password = cred->password;
734 else
736 username = session->internals.srp_username;
737 password = session->internals.srp_password;
740 if (username == NULL || password == NULL)
742 gnutls_assert ();
743 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
746 i = 0;
748 /* Read N
750 DECR_LEN (data_size, 2);
751 n_n = _gnutls_read_uint16 (&data[i]);
752 i += 2;
754 DECR_LEN (data_size, n_n);
755 data_n = &data[i];
756 i += n_n;
758 /* Read G
760 DECR_LEN (data_size, 2);
761 n_g = _gnutls_read_uint16 (&data[i]);
762 i += 2;
764 DECR_LEN (data_size, n_g);
765 data_g = &data[i];
766 i += n_g;
768 /* Read salt
770 DECR_LEN (data_size, 1);
771 n_s = data[i];
772 i += 1;
774 DECR_LEN (data_size, n_s);
775 data_s = &data[i];
776 i += n_s;
778 /* Read B
780 DECR_LEN (data_size, 2);
781 n_b = _gnutls_read_uint16 (&data[i]);
782 i += 2;
784 DECR_LEN (data_size, n_b);
785 data_b = &data[i];
786 i += n_b;
788 _n_s = n_s;
789 _n_g = n_g;
790 _n_n = n_n;
791 _n_b = n_b;
793 if (_gnutls_mpi_scan_nz (&N, data_n, &_n_n) != 0)
795 gnutls_assert ();
796 return GNUTLS_E_MPI_SCAN_FAILED;
799 if (_gnutls_mpi_scan_nz (&G, data_g, &_n_g) != 0)
801 gnutls_assert ();
802 return GNUTLS_E_MPI_SCAN_FAILED;
805 if (_gnutls_mpi_scan_nz (&B, data_b, &_n_b) != 0)
807 gnutls_assert ();
808 return GNUTLS_E_MPI_SCAN_FAILED;
812 /* Check if the g and n are from the SRP
813 * draft. Otherwise check if N is a prime and G
814 * a generator.
816 if ((ret = check_g_n (data_g, _n_g, data_n, _n_n)) < 0)
818 _gnutls_x509_log ("Checking the SRP group parameters.\n");
819 if ((ret = group_check_g_n (G, N)) < 0)
821 gnutls_assert ();
822 return ret;
826 /* Checks if b % n == 0
828 if ((ret = check_b_mod_n (B, N)) < 0)
830 gnutls_assert ();
831 return ret;
835 /* generate x = SHA(s | SHA(U | ":" | p))
836 * (or the equivalent using bcrypt)
838 if ((ret =
839 _gnutls_calc_srp_x (username, password, (opaque *) data_s, n_s,
840 &_n_g, hd)) < 0)
842 gnutls_assert ();
843 return ret;
846 if (_gnutls_mpi_scan_nz (&session->key->x, hd, &_n_g) != 0)
848 gnutls_assert ();
849 return GNUTLS_E_MPI_SCAN_FAILED;
853 return i; /* return the processed data
854 * needed in auth_srp_rsa.
858 #endif /* ENABLE_SRP */