Export new ABIs. Doc fixes for new APIs.
[gnutls.git] / lib / auth_srp.c
blob3f5eb55f7f754198926367042096e9938c9ac0a4
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 library 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>
40 const mod_auth_st srp_auth_struct = {
41 "SRP",
42 NULL,
43 NULL,
44 _gnutls_gen_srp_server_kx,
45 _gnutls_gen_srp_client_kx,
46 NULL,
47 NULL,
49 NULL,
50 NULL, /* certificate */
51 _gnutls_proc_srp_server_kx,
52 _gnutls_proc_srp_client_kx,
53 NULL,
54 NULL
58 #define _b session->key->b
59 #define B session->key->B
60 #define _a session->key->a
61 #define A session->key->A
62 #define N session->key->client_p
63 #define G session->key->client_g
64 #define V session->key->x
65 #define S session->key->KEY
67 /* Checks if b%n==0 which is a fatal srp error.
68 * Returns a proper error code in that case, and 0 when
69 * all are ok.
71 inline static int
72 check_b_mod_n (bigint_t b, bigint_t n)
74 int ret;
75 bigint_t r;
77 r = _gnutls_mpi_mod (b, n);
79 if (r == NULL)
81 gnutls_assert ();
82 return GNUTLS_E_MEMORY_ERROR;
85 ret = _gnutls_mpi_cmp_ui (r, 0);
87 _gnutls_mpi_release (&r);
89 if (ret == 0)
91 gnutls_assert ();
92 return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
95 return 0;
98 /* Checks if a%n==0,+1,-1%n which is a fatal srp error.
99 * Returns a proper error code in that case, and 0 when
100 * all are ok.
102 inline static int
103 check_a_mod_n (bigint_t a, bigint_t n)
105 int ret;
106 bigint_t r;
108 r = _gnutls_mpi_mod (a, n);
109 if (r == NULL)
111 gnutls_assert ();
112 return GNUTLS_E_MEMORY_ERROR;
115 ret = _gnutls_mpi_cmp_ui (r, 0);
117 _gnutls_mpi_release (&r);
119 if (ret == 0)
121 gnutls_assert ();
122 return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
125 return 0;
129 /* Send the first key exchange message ( g, n, s) and append the verifier algorithm number
130 * Data is allocated by the caller, and should have data_size size.
133 _gnutls_gen_srp_server_kx (gnutls_session_t session, opaque ** data)
135 int ret;
136 uint8_t *data_n, *data_s;
137 uint8_t *data_g;
138 char *username;
139 SRP_PWD_ENTRY *pwd_entry;
140 srp_server_auth_info_t info;
141 ssize_t data_size;
142 size_t n_b, tmp_size;
143 char buf[64];
144 uint8_t *data_b;
146 if ((ret =
147 _gnutls_auth_info_set (session, GNUTLS_CRD_SRP,
148 sizeof (srp_server_auth_info_st), 1)) < 0)
150 gnutls_assert ();
151 return ret;
154 info = _gnutls_get_auth_info (session);
155 username = info->username;
157 _gnutls_str_cpy (username, MAX_SRP_USERNAME,
158 session->security_parameters.extensions.srp_username);
160 ret = _gnutls_srp_pwd_read_entry (session, username, &pwd_entry);
162 if (ret < 0)
164 gnutls_assert ();
165 return ret;
168 /* copy from pwd_entry to local variables (actually in session) */
169 tmp_size = pwd_entry->g.size;
170 if (_gnutls_mpi_scan_nz (&G, pwd_entry->g.data, tmp_size) < 0)
172 gnutls_assert ();
173 return GNUTLS_E_MPI_SCAN_FAILED;
176 tmp_size = pwd_entry->n.size;
177 if (_gnutls_mpi_scan_nz (&N, pwd_entry->n.data, tmp_size) < 0)
179 gnutls_assert ();
180 return GNUTLS_E_MPI_SCAN_FAILED;
183 tmp_size = pwd_entry->v.size;
184 if (_gnutls_mpi_scan_nz (&V, pwd_entry->v.data, tmp_size) < 0)
186 gnutls_assert ();
187 return GNUTLS_E_MPI_SCAN_FAILED;
190 /* Calculate: B = (k*v + g^b) % N
192 B = _gnutls_calc_srp_B (&_b, G, N, V);
193 if (B == NULL)
195 gnutls_assert ();
196 return GNUTLS_E_MEMORY_ERROR;
199 if (_gnutls_mpi_print (B, NULL, &n_b) != 0)
201 gnutls_assert ();
202 return GNUTLS_E_MPI_PRINT_FAILED;
206 /* Allocate size to hold the N, g, s, B
209 data_size = (pwd_entry->n.size + 2 + pwd_entry->g.size + 2 +
210 pwd_entry->salt.size + 1) + (n_b + 2);
212 (*data) = gnutls_malloc (data_size);
213 if ((*data) == NULL)
215 gnutls_assert ();
216 return GNUTLS_E_MEMORY_ERROR;
219 /* copy N (mod n)
221 data_n = *data;
222 _gnutls_write_datum16 (data_n, pwd_entry->n);
225 /* copy G (generator) to data
227 data_g = &data_n[2 + pwd_entry->n.size];
228 _gnutls_write_datum16 (data_g, pwd_entry->g);
231 /* copy the salt
233 data_s = &data_g[2 + pwd_entry->g.size];
234 _gnutls_write_datum8 (data_s, pwd_entry->salt);
237 /* Copy the B value
240 data_b = &data_s[1 + pwd_entry->salt.size];
241 if (_gnutls_mpi_print (B, &data_b[2], &n_b) != 0)
243 gnutls_assert ();
244 return GNUTLS_E_MPI_PRINT_FAILED;
247 _gnutls_write_uint16 (n_b, data_b);
249 _gnutls_hard_log ("INT: SRP B[%d]: %s\n", (int) n_b,
250 _gnutls_bin2hex (&data_b[2], n_b, buf, sizeof (buf)));
252 _gnutls_srp_entry_free (pwd_entry);
254 return data_size;
257 /* return A = g^a % N */
259 _gnutls_gen_srp_client_kx (gnutls_session_t session, opaque ** data)
261 size_t n_a;
262 int ret;
263 uint8_t *data_a;
264 char *username, *password;
265 char buf[64];
266 gnutls_srp_client_credentials_t cred;
269 cred = (gnutls_srp_client_credentials_t)
270 _gnutls_get_cred (session->key, GNUTLS_CRD_SRP, NULL);
272 if (cred == NULL)
274 gnutls_assert ();
275 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
278 if (session->internals.srp_username == NULL)
280 username = cred->username;
281 password = cred->password;
283 else
285 username = session->internals.srp_username;
286 password = session->internals.srp_password;
289 if (username == NULL || password == NULL)
291 gnutls_assert ();
292 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
295 /* calc A = g^a % N
297 if (G == NULL || N == NULL)
299 gnutls_assert ();
300 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
303 A = _gnutls_calc_srp_A (&_a, G, N);
304 if (A == NULL)
306 gnutls_assert ();
307 return GNUTLS_E_MEMORY_ERROR;
310 /* Rest of SRP calculations
313 /* calculate u */
314 session->key->u = _gnutls_calc_srp_u (A, B, N);
315 if (session->key->u == NULL)
317 gnutls_assert ();
318 return GNUTLS_E_MEMORY_ERROR;
321 _gnutls_mpi_log ("SRP U: ", session->key->u);
323 /* S = (B - g^x) ^ (a + u * x) % N */
324 S = _gnutls_calc_srp_S2 (B, G, session->key->x, _a, session->key->u, N);
325 if (S == NULL)
327 gnutls_assert ();
328 return GNUTLS_E_MEMORY_ERROR;
331 _gnutls_mpi_log ("SRP B: ", B);
333 _gnutls_mpi_release (&_b);
334 _gnutls_mpi_release (&V);
335 _gnutls_mpi_release (&session->key->u);
336 _gnutls_mpi_release (&B);
338 ret = _gnutls_mpi_dprint (session->key->KEY, &session->key->key);
339 _gnutls_mpi_release (&S);
341 if (ret < 0)
343 gnutls_assert ();
344 return ret;
347 if (_gnutls_mpi_print (A, NULL, &n_a) != 0)
349 gnutls_assert ();
350 return GNUTLS_E_MPI_PRINT_FAILED;
353 (*data) = gnutls_malloc (n_a + 2);
354 if ((*data) == NULL)
356 gnutls_assert ();
357 return GNUTLS_E_MEMORY_ERROR;
360 /* copy A */
361 data_a = (*data);
362 if (_gnutls_mpi_print (A, &data_a[2], &n_a) != 0)
364 gnutls_free (*data);
365 return GNUTLS_E_MPI_PRINT_FAILED;
368 _gnutls_hard_log ("INT: SRP A[%d]: %s\n", (int) n_a,
369 _gnutls_bin2hex (&data_a[2], n_a, buf, sizeof (buf)));
371 _gnutls_mpi_release (&A);
373 _gnutls_write_uint16 (n_a, data_a);
375 return n_a + 2;
379 /* just read A and put it to session */
381 _gnutls_proc_srp_client_kx (gnutls_session_t session, opaque * data,
382 size_t _data_size)
384 size_t _n_A;
385 ssize_t data_size = _data_size;
386 int ret;
388 DECR_LEN (data_size, 2);
389 _n_A = _gnutls_read_uint16 (&data[0]);
391 DECR_LEN (data_size, _n_A);
392 if (_gnutls_mpi_scan_nz (&A, &data[2], _n_A) || A == NULL)
394 gnutls_assert ();
395 return GNUTLS_E_MPI_SCAN_FAILED;
398 _gnutls_mpi_log ("SRP A: ", A);
399 _gnutls_mpi_log ("SRP B: ", B);
401 /* Checks if A % n == 0.
403 if ((ret = check_a_mod_n (A, N)) < 0)
405 gnutls_assert ();
406 return ret;
409 /* Start the SRP calculations.
410 * - Calculate u
412 session->key->u = _gnutls_calc_srp_u (A, B, N);
413 if (session->key->u == NULL)
415 gnutls_assert ();
416 return GNUTLS_E_MEMORY_ERROR;
419 _gnutls_mpi_log ("SRP U: ", session->key->u);
421 /* S = (A * v^u) ^ b % N
423 S = _gnutls_calc_srp_S1 (A, _b, session->key->u, V, N);
424 if (S == NULL)
426 gnutls_assert ();
427 return GNUTLS_E_MEMORY_ERROR;
430 _gnutls_mpi_log ("SRP S: ", S);
432 _gnutls_mpi_release (&A);
433 _gnutls_mpi_release (&_b);
434 _gnutls_mpi_release (&V);
435 _gnutls_mpi_release (&session->key->u);
436 _gnutls_mpi_release (&B);
438 ret = _gnutls_mpi_dprint (session->key->KEY, &session->key->key);
439 _gnutls_mpi_release (&S);
441 if (ret < 0)
443 gnutls_assert ();
444 return ret;
447 return 0;
452 /* Static parameters according to draft-ietf-tls-srp-07
453 * Note that if more parameters are added check_g_n()
454 * and _gnutls_srp_entry_free() should be changed.
456 static const unsigned char srp_params_1024[] = {
457 0xEE, 0xAF, 0x0A, 0xB9, 0xAD, 0xB3, 0x8D, 0xD6,
458 0x9C, 0x33, 0xF8, 0x0A, 0xFA, 0x8F, 0xC5, 0xE8,
459 0x60, 0x72, 0x61, 0x87, 0x75, 0xFF, 0x3C, 0x0B,
460 0x9E, 0xA2, 0x31, 0x4C, 0x9C, 0x25, 0x65, 0x76,
461 0xD6, 0x74, 0xDF, 0x74, 0x96, 0xEA, 0x81, 0xD3,
462 0x38, 0x3B, 0x48, 0x13, 0xD6, 0x92, 0xC6, 0xE0,
463 0xE0, 0xD5, 0xD8, 0xE2, 0x50, 0xB9, 0x8B, 0xE4,
464 0x8E, 0x49, 0x5C, 0x1D, 0x60, 0x89, 0xDA, 0xD1,
465 0x5D, 0xC7, 0xD7, 0xB4, 0x61, 0x54, 0xD6, 0xB6,
466 0xCE, 0x8E, 0xF4, 0xAD, 0x69, 0xB1, 0x5D, 0x49,
467 0x82, 0x55, 0x9B, 0x29, 0x7B, 0xCF, 0x18, 0x85,
468 0xC5, 0x29, 0xF5, 0x66, 0x66, 0x0E, 0x57, 0xEC,
469 0x68, 0xED, 0xBC, 0x3C, 0x05, 0x72, 0x6C, 0xC0,
470 0x2F, 0xD4, 0xCB, 0xF4, 0x97, 0x6E, 0xAA, 0x9A,
471 0xFD, 0x51, 0x38, 0xFE, 0x83, 0x76, 0x43, 0x5B,
472 0x9F, 0xC6, 0x1D, 0x2F, 0xC0, 0xEB, 0x06, 0xE3
475 static const unsigned char srp_generator = 0x02;
477 const gnutls_datum_t gnutls_srp_1024_group_prime = {
478 (void *) srp_params_1024, sizeof (srp_params_1024)
481 const gnutls_datum_t gnutls_srp_1024_group_generator = {
482 (void *) &srp_generator, sizeof (srp_generator)
485 static const unsigned char srp_params_1536[] = {
486 0x9D, 0xEF, 0x3C, 0xAF, 0xB9, 0x39, 0x27, 0x7A, 0xB1,
487 0xF1, 0x2A, 0x86, 0x17, 0xA4, 0x7B, 0xBB, 0xDB, 0xA5,
488 0x1D, 0xF4, 0x99, 0xAC, 0x4C, 0x80, 0xBE, 0xEE, 0xA9,
489 0x61, 0x4B, 0x19, 0xCC, 0x4D, 0x5F, 0x4F, 0x5F, 0x55,
490 0x6E, 0x27, 0xCB, 0xDE, 0x51, 0xC6, 0xA9, 0x4B, 0xE4,
491 0x60, 0x7A, 0x29, 0x15, 0x58, 0x90, 0x3B, 0xA0, 0xD0,
492 0xF8, 0x43, 0x80, 0xB6, 0x55, 0xBB, 0x9A, 0x22, 0xE8,
493 0xDC, 0xDF, 0x02, 0x8A, 0x7C, 0xEC, 0x67, 0xF0, 0xD0,
494 0x81, 0x34, 0xB1, 0xC8, 0xB9, 0x79, 0x89, 0x14, 0x9B,
495 0x60, 0x9E, 0x0B, 0xE3, 0xBA, 0xB6, 0x3D, 0x47, 0x54,
496 0x83, 0x81, 0xDB, 0xC5, 0xB1, 0xFC, 0x76, 0x4E, 0x3F,
497 0x4B, 0x53, 0xDD, 0x9D, 0xA1, 0x15, 0x8B, 0xFD, 0x3E,
498 0x2B, 0x9C, 0x8C, 0xF5, 0x6E, 0xDF, 0x01, 0x95, 0x39,
499 0x34, 0x96, 0x27, 0xDB, 0x2F, 0xD5, 0x3D, 0x24, 0xB7,
500 0xC4, 0x86, 0x65, 0x77, 0x2E, 0x43, 0x7D, 0x6C, 0x7F,
501 0x8C, 0xE4, 0x42, 0x73, 0x4A, 0xF7, 0xCC, 0xB7, 0xAE,
502 0x83, 0x7C, 0x26, 0x4A, 0xE3, 0xA9, 0xBE, 0xB8, 0x7F,
503 0x8A, 0x2F, 0xE9, 0xB8, 0xB5, 0x29, 0x2E, 0x5A, 0x02,
504 0x1F, 0xFF, 0x5E, 0x91, 0x47, 0x9E, 0x8C, 0xE7, 0xA2,
505 0x8C, 0x24, 0x42, 0xC6, 0xF3, 0x15, 0x18, 0x0F, 0x93,
506 0x49, 0x9A, 0x23, 0x4D, 0xCF, 0x76, 0xE3, 0xFE, 0xD1,
507 0x35, 0xF9, 0xBB
510 const gnutls_datum_t gnutls_srp_1536_group_prime = {
511 (void *) srp_params_1536, sizeof (srp_params_1536)
514 const gnutls_datum_t gnutls_srp_1536_group_generator = {
515 (void *) &srp_generator, sizeof (srp_generator)
518 static const unsigned char srp_params_2048[] = {
519 0xAC, 0x6B, 0xDB, 0x41, 0x32, 0x4A, 0x9A, 0x9B, 0xF1,
520 0x66, 0xDE, 0x5E, 0x13, 0x89, 0x58, 0x2F, 0xAF, 0x72,
521 0xB6, 0x65, 0x19, 0x87, 0xEE, 0x07, 0xFC, 0x31, 0x92,
522 0x94, 0x3D, 0xB5, 0x60, 0x50, 0xA3, 0x73, 0x29, 0xCB,
523 0xB4, 0xA0, 0x99, 0xED, 0x81, 0x93, 0xE0, 0x75, 0x77,
524 0x67, 0xA1, 0x3D, 0xD5, 0x23, 0x12, 0xAB, 0x4B, 0x03,
525 0x31, 0x0D, 0xCD, 0x7F, 0x48, 0xA9, 0xDA, 0x04, 0xFD,
526 0x50, 0xE8, 0x08, 0x39, 0x69, 0xED, 0xB7, 0x67, 0xB0,
527 0xCF, 0x60, 0x95, 0x17, 0x9A, 0x16, 0x3A, 0xB3, 0x66,
528 0x1A, 0x05, 0xFB, 0xD5, 0xFA, 0xAA, 0xE8, 0x29, 0x18,
529 0xA9, 0x96, 0x2F, 0x0B, 0x93, 0xB8, 0x55, 0xF9, 0x79,
530 0x93, 0xEC, 0x97, 0x5E, 0xEA, 0xA8, 0x0D, 0x74, 0x0A,
531 0xDB, 0xF4, 0xFF, 0x74, 0x73, 0x59, 0xD0, 0x41, 0xD5,
532 0xC3, 0x3E, 0xA7, 0x1D, 0x28, 0x1E, 0x44, 0x6B, 0x14,
533 0x77, 0x3B, 0xCA, 0x97, 0xB4, 0x3A, 0x23, 0xFB, 0x80,
534 0x16, 0x76, 0xBD, 0x20, 0x7A, 0x43, 0x6C, 0x64, 0x81,
535 0xF1, 0xD2, 0xB9, 0x07, 0x87, 0x17, 0x46, 0x1A, 0x5B,
536 0x9D, 0x32, 0xE6, 0x88, 0xF8, 0x77, 0x48, 0x54, 0x45,
537 0x23, 0xB5, 0x24, 0xB0, 0xD5, 0x7D, 0x5E, 0xA7, 0x7A,
538 0x27, 0x75, 0xD2, 0xEC, 0xFA, 0x03, 0x2C, 0xFB, 0xDB,
539 0xF5, 0x2F, 0xB3, 0x78, 0x61, 0x60, 0x27, 0x90, 0x04,
540 0xE5, 0x7A, 0xE6, 0xAF, 0x87, 0x4E, 0x73, 0x03, 0xCE,
541 0x53, 0x29, 0x9C, 0xCC, 0x04, 0x1C, 0x7B, 0xC3, 0x08,
542 0xD8, 0x2A, 0x56, 0x98, 0xF3, 0xA8, 0xD0, 0xC3, 0x82,
543 0x71, 0xAE, 0x35, 0xF8, 0xE9, 0xDB, 0xFB, 0xB6, 0x94,
544 0xB5, 0xC8, 0x03, 0xD8, 0x9F, 0x7A, 0xE4, 0x35, 0xDE,
545 0x23, 0x6D, 0x52, 0x5F, 0x54, 0x75, 0x9B, 0x65, 0xE3,
546 0x72, 0xFC, 0xD6, 0x8E, 0xF2, 0x0F, 0xA7, 0x11, 0x1F,
547 0x9E, 0x4A, 0xFF, 0x73
550 const gnutls_datum_t gnutls_srp_2048_group_prime = {
551 (void *) srp_params_2048, sizeof (srp_params_2048)
554 const gnutls_datum_t gnutls_srp_2048_group_generator = {
555 (void *) &srp_generator, sizeof (srp_generator)
559 /* Check if G and N are parameters from the SRP draft.
561 static int
562 check_g_n (const opaque * g, size_t n_g, const opaque * n, size_t n_n)
565 if (n_g != 1 || g[0] != srp_generator)
567 gnutls_assert ();
568 return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
571 if (n_n == sizeof (srp_params_1024) &&
572 memcmp (srp_params_1024, n, n_n) == 0)
574 return 0;
577 if (n_n == sizeof (srp_params_1536) &&
578 memcmp (srp_params_1536, n, n_n) == 0)
580 return 0;
583 if (n_n == sizeof (srp_params_2048) &&
584 memcmp (srp_params_2048, n, n_n) == 0)
586 return 0;
589 gnutls_assert ();
590 return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
593 /* Check if N is a prime and G a generator of the
594 * group. This is check only done if N is big enough.
595 * Otherwise only the included parameters must be used.
597 static int
598 group_check_g_n (gnutls_session_t session, bigint_t g, bigint_t n)
600 bigint_t q = NULL, two = NULL, w = NULL;
601 int ret;
603 if (_gnutls_mpi_get_nbits (n) < (session->internals.srp_prime_bits
604 ? session->internals.srp_prime_bits
605 : 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)
616 _gnutls_mpi_log ("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, q, two);
645 if (_gnutls_prime_check (q) != 0)
647 /* N was not on the form N=2q+1, where q = prime
649 _gnutls_mpi_log ("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 (session, 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 */