updated licenses
[gnutls.git] / lib / auth / srp.c
blob2bb619116e596b9ea59a85a65f59cea28fab73b7
1 /*
2 * Copyright (C) 2001-2012 Free Software Foundation, Inc.
4 * Author: Nikos Mavrogiannopoulos
6 * This file is part of GnuTLS.
8 * The GnuTLS 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 3 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 License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>
23 #include <gnutls_int.h>
25 #ifdef ENABLE_SRP
27 #include "gnutls_errors.h"
28 #include <auth/srp_passwd.h>
29 #include "gnutls_auth.h"
30 #include "gnutls_auth.h"
31 #include "gnutls_srp.h"
32 #include "gnutls_num.h"
33 #include <auth/srp.h>
34 #include <gnutls_str.h>
35 #include <gnutls_datum.h>
36 #include <ext/srp.h>
38 const mod_auth_st srp_auth_struct = {
39 "SRP",
40 NULL,
41 NULL,
42 _gnutls_gen_srp_server_kx,
43 _gnutls_gen_srp_client_kx,
44 NULL,
45 NULL,
47 NULL,
48 NULL, /* certificate */
49 _gnutls_proc_srp_server_kx,
50 _gnutls_proc_srp_client_kx,
51 NULL,
52 NULL
56 #define _b session->key->b
57 #define B session->key->B
58 #define _a session->key->a
59 #define A session->key->A
60 #define N session->key->client_p
61 #define G session->key->client_g
62 #define V session->key->x
63 #define S session->key->KEY
65 /* Checks if b%n==0 which is a fatal srp error.
66 * Returns a proper error code in that case, and 0 when
67 * all are ok.
69 inline static int
70 check_b_mod_n (bigint_t b, bigint_t n)
72 int ret;
73 bigint_t r;
75 r = _gnutls_mpi_mod (b, n);
77 if (r == NULL)
79 gnutls_assert ();
80 return GNUTLS_E_MEMORY_ERROR;
83 ret = _gnutls_mpi_cmp_ui (r, 0);
85 _gnutls_mpi_release (&r);
87 if (ret == 0)
89 gnutls_assert ();
90 return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
93 return 0;
96 /* Checks if a%n==0,+1,-1%n which is a fatal srp error.
97 * Returns a proper error code in that case, and 0 when
98 * all are ok.
100 inline static int
101 check_a_mod_n (bigint_t a, bigint_t n)
103 int ret;
104 bigint_t r;
106 r = _gnutls_mpi_mod (a, n);
107 if (r == NULL)
109 gnutls_assert ();
110 return GNUTLS_E_MEMORY_ERROR;
113 ret = _gnutls_mpi_cmp_ui (r, 0);
115 _gnutls_mpi_release (&r);
117 if (ret == 0)
119 gnutls_assert ();
120 return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
123 return 0;
127 /* Send the first key exchange message ( g, n, s) and append the verifier algorithm number
128 * Data is allocated by the caller, and should have data_size size.
131 _gnutls_gen_srp_server_kx (gnutls_session_t session, gnutls_buffer_st* data)
133 int ret;
134 char *username;
135 SRP_PWD_ENTRY *pwd_entry;
136 srp_server_auth_info_t info;
137 size_t tmp_size;
138 extension_priv_data_t epriv;
139 srp_ext_st *priv;
141 ret = _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_SRP, &epriv);
142 if (ret < 0) /* peer didn't send a username */
144 gnutls_assert ();
145 return GNUTLS_E_UNKNOWN_SRP_USERNAME;
147 priv = epriv.ptr;
149 if ((ret =
150 _gnutls_auth_info_set (session, GNUTLS_CRD_SRP,
151 sizeof (srp_server_auth_info_st), 1)) < 0)
153 gnutls_assert ();
154 return ret;
157 info = _gnutls_get_auth_info (session);
158 username = info->username;
160 _gnutls_str_cpy (username, MAX_USERNAME_SIZE, priv->username);
162 ret = _gnutls_srp_pwd_read_entry (session, username, &pwd_entry);
164 if (ret < 0)
166 gnutls_assert ();
167 return ret;
170 /* copy from pwd_entry to local variables (actually in session) */
171 tmp_size = pwd_entry->g.size;
172 if (_gnutls_mpi_scan_nz (&G, pwd_entry->g.data, tmp_size) < 0)
174 gnutls_assert ();
175 ret = GNUTLS_E_MPI_SCAN_FAILED;
176 goto cleanup;
179 tmp_size = pwd_entry->n.size;
180 if (_gnutls_mpi_scan_nz (&N, pwd_entry->n.data, tmp_size) < 0)
182 gnutls_assert ();
183 ret = GNUTLS_E_MPI_SCAN_FAILED;
184 goto cleanup;
187 tmp_size = pwd_entry->v.size;
188 if (_gnutls_mpi_scan_nz (&V, pwd_entry->v.data, tmp_size) < 0)
190 gnutls_assert ();
191 ret = GNUTLS_E_MPI_SCAN_FAILED;
192 goto cleanup;
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 ret = GNUTLS_E_MEMORY_ERROR;
202 goto cleanup;
205 /* copy N (mod n)
207 ret = _gnutls_buffer_append_data_prefix( data, 16, pwd_entry->n.data,
208 pwd_entry->n.size);
209 if (ret < 0)
211 gnutls_assert();
212 goto cleanup;
215 /* copy G (generator) to data
217 ret = _gnutls_buffer_append_data_prefix( data, 16, pwd_entry->g.data,
218 pwd_entry->g.size);
219 if (ret < 0)
221 gnutls_assert();
222 goto cleanup;
225 /* copy the salt
227 ret = _gnutls_buffer_append_data_prefix( data, 8, pwd_entry->salt.data,
228 pwd_entry->salt.size);
229 if (ret < 0)
231 gnutls_assert();
232 goto cleanup;
235 /* Copy the B value
238 ret = _gnutls_buffer_append_mpi( data, 16, B, 0);
239 if (ret < 0)
241 gnutls_assert();
242 goto cleanup;
245 _gnutls_mpi_log ("SRP B: ", B);
247 ret = data->length;
249 cleanup:
250 _gnutls_srp_entry_free (pwd_entry);
251 return ret;
254 /* return A = g^a % N */
256 _gnutls_gen_srp_client_kx (gnutls_session_t session, gnutls_buffer_st* data)
258 int ret;
259 char *username, *password;
260 gnutls_srp_client_credentials_t cred;
261 extension_priv_data_t epriv;
262 srp_ext_st *priv;
264 ret = _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_SRP, &epriv);
265 if (ret < 0) /* peer didn't send a username */
267 gnutls_assert ();
268 return GNUTLS_E_UNKNOWN_SRP_USERNAME;
270 priv = epriv.ptr;
272 cred = (gnutls_srp_client_credentials_t)
273 _gnutls_get_cred (session->key, GNUTLS_CRD_SRP, NULL);
275 if (cred == NULL)
277 gnutls_assert ();
278 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
281 if (priv->username == NULL)
283 username = cred->username;
284 password = cred->password;
286 else
289 username = priv->username;
290 password = priv->password;
293 if (username == NULL || password == NULL)
295 gnutls_assert ();
296 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
299 /* calc A = g^a % N
301 if (G == NULL || N == NULL)
303 gnutls_assert ();
304 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
307 A = _gnutls_calc_srp_A (&_a, G, N);
308 if (A == NULL)
310 gnutls_assert ();
311 return GNUTLS_E_MEMORY_ERROR;
314 /* Rest of SRP calculations
317 /* calculate u */
318 session->key->u = _gnutls_calc_srp_u (A, B, N);
319 if (session->key->u == NULL)
321 gnutls_assert ();
322 return GNUTLS_E_MEMORY_ERROR;
325 _gnutls_mpi_log ("SRP U: ", session->key->u);
327 /* S = (B - g^x) ^ (a + u * x) % N */
328 S = _gnutls_calc_srp_S2 (B, G, session->key->x, _a, session->key->u, N);
329 if (S == NULL)
331 gnutls_assert ();
332 return GNUTLS_E_MEMORY_ERROR;
335 _gnutls_mpi_log ("SRP B: ", B);
337 _gnutls_mpi_release (&_b);
338 _gnutls_mpi_release (&V);
339 _gnutls_mpi_release (&session->key->u);
340 _gnutls_mpi_release (&B);
342 ret = _gnutls_mpi_dprint (session->key->KEY, &session->key->key);
343 _gnutls_mpi_release (&S);
345 if (ret < 0)
347 gnutls_assert ();
348 return ret;
351 ret = _gnutls_buffer_append_mpi(data, 16, A, 0);
352 if (ret < 0)
353 return gnutls_assert_val(ret);
355 _gnutls_mpi_log ("SRP A: ", A);
357 _gnutls_mpi_release (&A);
359 return data->length;
363 /* just read A and put it to session */
365 _gnutls_proc_srp_client_kx (gnutls_session_t session, uint8_t * data,
366 size_t _data_size)
368 size_t _n_A;
369 ssize_t data_size = _data_size;
370 int ret;
372 DECR_LEN (data_size, 2);
373 _n_A = _gnutls_read_uint16 (&data[0]);
375 DECR_LEN (data_size, _n_A);
376 if (_gnutls_mpi_scan_nz (&A, &data[2], _n_A) || A == NULL)
378 gnutls_assert ();
379 return GNUTLS_E_MPI_SCAN_FAILED;
382 _gnutls_mpi_log ("SRP A: ", A);
383 _gnutls_mpi_log ("SRP B: ", B);
385 /* Checks if A % n == 0.
387 if ((ret = check_a_mod_n (A, N)) < 0)
389 gnutls_assert ();
390 return ret;
393 /* Start the SRP calculations.
394 * - Calculate u
396 session->key->u = _gnutls_calc_srp_u (A, B, N);
397 if (session->key->u == NULL)
399 gnutls_assert ();
400 return GNUTLS_E_MEMORY_ERROR;
403 _gnutls_mpi_log ("SRP U: ", session->key->u);
405 /* S = (A * v^u) ^ b % N
407 S = _gnutls_calc_srp_S1 (A, _b, session->key->u, V, N);
408 if (S == NULL)
410 gnutls_assert ();
411 return GNUTLS_E_MEMORY_ERROR;
414 _gnutls_mpi_log ("SRP S: ", S);
416 _gnutls_mpi_release (&A);
417 _gnutls_mpi_release (&_b);
418 _gnutls_mpi_release (&V);
419 _gnutls_mpi_release (&session->key->u);
420 _gnutls_mpi_release (&B);
422 ret = _gnutls_mpi_dprint (session->key->KEY, &session->key->key);
423 _gnutls_mpi_release (&S);
425 if (ret < 0)
427 gnutls_assert ();
428 return ret;
431 return 0;
436 /* Static parameters according to draft-ietf-tls-srp-07
437 * Note that if more parameters are added check_g_n()
438 * and _gnutls_srp_entry_free() should be changed.
440 static const unsigned char srp_params_1024[] = {
441 0xEE, 0xAF, 0x0A, 0xB9, 0xAD, 0xB3, 0x8D, 0xD6,
442 0x9C, 0x33, 0xF8, 0x0A, 0xFA, 0x8F, 0xC5, 0xE8,
443 0x60, 0x72, 0x61, 0x87, 0x75, 0xFF, 0x3C, 0x0B,
444 0x9E, 0xA2, 0x31, 0x4C, 0x9C, 0x25, 0x65, 0x76,
445 0xD6, 0x74, 0xDF, 0x74, 0x96, 0xEA, 0x81, 0xD3,
446 0x38, 0x3B, 0x48, 0x13, 0xD6, 0x92, 0xC6, 0xE0,
447 0xE0, 0xD5, 0xD8, 0xE2, 0x50, 0xB9, 0x8B, 0xE4,
448 0x8E, 0x49, 0x5C, 0x1D, 0x60, 0x89, 0xDA, 0xD1,
449 0x5D, 0xC7, 0xD7, 0xB4, 0x61, 0x54, 0xD6, 0xB6,
450 0xCE, 0x8E, 0xF4, 0xAD, 0x69, 0xB1, 0x5D, 0x49,
451 0x82, 0x55, 0x9B, 0x29, 0x7B, 0xCF, 0x18, 0x85,
452 0xC5, 0x29, 0xF5, 0x66, 0x66, 0x0E, 0x57, 0xEC,
453 0x68, 0xED, 0xBC, 0x3C, 0x05, 0x72, 0x6C, 0xC0,
454 0x2F, 0xD4, 0xCB, 0xF4, 0x97, 0x6E, 0xAA, 0x9A,
455 0xFD, 0x51, 0x38, 0xFE, 0x83, 0x76, 0x43, 0x5B,
456 0x9F, 0xC6, 0x1D, 0x2F, 0xC0, 0xEB, 0x06, 0xE3
459 static const unsigned char srp_generator = 0x02;
460 static const unsigned char srp3072_generator = 0x05;
462 const gnutls_datum_t gnutls_srp_1024_group_prime = {
463 (void *) srp_params_1024, sizeof (srp_params_1024)
466 const gnutls_datum_t gnutls_srp_1024_group_generator = {
467 (void *) &srp_generator, sizeof (srp_generator)
470 static const unsigned char srp_params_1536[] = {
471 0x9D, 0xEF, 0x3C, 0xAF, 0xB9, 0x39, 0x27, 0x7A, 0xB1,
472 0xF1, 0x2A, 0x86, 0x17, 0xA4, 0x7B, 0xBB, 0xDB, 0xA5,
473 0x1D, 0xF4, 0x99, 0xAC, 0x4C, 0x80, 0xBE, 0xEE, 0xA9,
474 0x61, 0x4B, 0x19, 0xCC, 0x4D, 0x5F, 0x4F, 0x5F, 0x55,
475 0x6E, 0x27, 0xCB, 0xDE, 0x51, 0xC6, 0xA9, 0x4B, 0xE4,
476 0x60, 0x7A, 0x29, 0x15, 0x58, 0x90, 0x3B, 0xA0, 0xD0,
477 0xF8, 0x43, 0x80, 0xB6, 0x55, 0xBB, 0x9A, 0x22, 0xE8,
478 0xDC, 0xDF, 0x02, 0x8A, 0x7C, 0xEC, 0x67, 0xF0, 0xD0,
479 0x81, 0x34, 0xB1, 0xC8, 0xB9, 0x79, 0x89, 0x14, 0x9B,
480 0x60, 0x9E, 0x0B, 0xE3, 0xBA, 0xB6, 0x3D, 0x47, 0x54,
481 0x83, 0x81, 0xDB, 0xC5, 0xB1, 0xFC, 0x76, 0x4E, 0x3F,
482 0x4B, 0x53, 0xDD, 0x9D, 0xA1, 0x15, 0x8B, 0xFD, 0x3E,
483 0x2B, 0x9C, 0x8C, 0xF5, 0x6E, 0xDF, 0x01, 0x95, 0x39,
484 0x34, 0x96, 0x27, 0xDB, 0x2F, 0xD5, 0x3D, 0x24, 0xB7,
485 0xC4, 0x86, 0x65, 0x77, 0x2E, 0x43, 0x7D, 0x6C, 0x7F,
486 0x8C, 0xE4, 0x42, 0x73, 0x4A, 0xF7, 0xCC, 0xB7, 0xAE,
487 0x83, 0x7C, 0x26, 0x4A, 0xE3, 0xA9, 0xBE, 0xB8, 0x7F,
488 0x8A, 0x2F, 0xE9, 0xB8, 0xB5, 0x29, 0x2E, 0x5A, 0x02,
489 0x1F, 0xFF, 0x5E, 0x91, 0x47, 0x9E, 0x8C, 0xE7, 0xA2,
490 0x8C, 0x24, 0x42, 0xC6, 0xF3, 0x15, 0x18, 0x0F, 0x93,
491 0x49, 0x9A, 0x23, 0x4D, 0xCF, 0x76, 0xE3, 0xFE, 0xD1,
492 0x35, 0xF9, 0xBB
495 const gnutls_datum_t gnutls_srp_1536_group_prime = {
496 (void *) srp_params_1536, sizeof (srp_params_1536)
499 const gnutls_datum_t gnutls_srp_1536_group_generator = {
500 (void *) &srp_generator, sizeof (srp_generator)
503 static const unsigned char srp_params_2048[] = {
504 0xAC, 0x6B, 0xDB, 0x41, 0x32, 0x4A, 0x9A, 0x9B, 0xF1,
505 0x66, 0xDE, 0x5E, 0x13, 0x89, 0x58, 0x2F, 0xAF, 0x72,
506 0xB6, 0x65, 0x19, 0x87, 0xEE, 0x07, 0xFC, 0x31, 0x92,
507 0x94, 0x3D, 0xB5, 0x60, 0x50, 0xA3, 0x73, 0x29, 0xCB,
508 0xB4, 0xA0, 0x99, 0xED, 0x81, 0x93, 0xE0, 0x75, 0x77,
509 0x67, 0xA1, 0x3D, 0xD5, 0x23, 0x12, 0xAB, 0x4B, 0x03,
510 0x31, 0x0D, 0xCD, 0x7F, 0x48, 0xA9, 0xDA, 0x04, 0xFD,
511 0x50, 0xE8, 0x08, 0x39, 0x69, 0xED, 0xB7, 0x67, 0xB0,
512 0xCF, 0x60, 0x95, 0x17, 0x9A, 0x16, 0x3A, 0xB3, 0x66,
513 0x1A, 0x05, 0xFB, 0xD5, 0xFA, 0xAA, 0xE8, 0x29, 0x18,
514 0xA9, 0x96, 0x2F, 0x0B, 0x93, 0xB8, 0x55, 0xF9, 0x79,
515 0x93, 0xEC, 0x97, 0x5E, 0xEA, 0xA8, 0x0D, 0x74, 0x0A,
516 0xDB, 0xF4, 0xFF, 0x74, 0x73, 0x59, 0xD0, 0x41, 0xD5,
517 0xC3, 0x3E, 0xA7, 0x1D, 0x28, 0x1E, 0x44, 0x6B, 0x14,
518 0x77, 0x3B, 0xCA, 0x97, 0xB4, 0x3A, 0x23, 0xFB, 0x80,
519 0x16, 0x76, 0xBD, 0x20, 0x7A, 0x43, 0x6C, 0x64, 0x81,
520 0xF1, 0xD2, 0xB9, 0x07, 0x87, 0x17, 0x46, 0x1A, 0x5B,
521 0x9D, 0x32, 0xE6, 0x88, 0xF8, 0x77, 0x48, 0x54, 0x45,
522 0x23, 0xB5, 0x24, 0xB0, 0xD5, 0x7D, 0x5E, 0xA7, 0x7A,
523 0x27, 0x75, 0xD2, 0xEC, 0xFA, 0x03, 0x2C, 0xFB, 0xDB,
524 0xF5, 0x2F, 0xB3, 0x78, 0x61, 0x60, 0x27, 0x90, 0x04,
525 0xE5, 0x7A, 0xE6, 0xAF, 0x87, 0x4E, 0x73, 0x03, 0xCE,
526 0x53, 0x29, 0x9C, 0xCC, 0x04, 0x1C, 0x7B, 0xC3, 0x08,
527 0xD8, 0x2A, 0x56, 0x98, 0xF3, 0xA8, 0xD0, 0xC3, 0x82,
528 0x71, 0xAE, 0x35, 0xF8, 0xE9, 0xDB, 0xFB, 0xB6, 0x94,
529 0xB5, 0xC8, 0x03, 0xD8, 0x9F, 0x7A, 0xE4, 0x35, 0xDE,
530 0x23, 0x6D, 0x52, 0x5F, 0x54, 0x75, 0x9B, 0x65, 0xE3,
531 0x72, 0xFC, 0xD6, 0x8E, 0xF2, 0x0F, 0xA7, 0x11, 0x1F,
532 0x9E, 0x4A, 0xFF, 0x73
535 const gnutls_datum_t gnutls_srp_2048_group_prime = {
536 (void *) srp_params_2048, sizeof (srp_params_2048)
539 const gnutls_datum_t gnutls_srp_2048_group_generator = {
540 (void *) &srp_generator, sizeof (srp_generator)
543 static const unsigned char srp_params_3072[] = {
544 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9,
545 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6,
546 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E,
547 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
548 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E,
549 0x34, 0x04, 0xDD, 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A,
550 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14,
551 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
552 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4,
553 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF,
554 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, 0xEE, 0x38, 0x6B,
555 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
556 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC,
557 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63,
558 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3,
559 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
560 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C,
561 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5,
562 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35,
563 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
564 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E,
565 0x36, 0xCE, 0x3B, 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E,
566 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2,
567 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
568 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39,
569 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2,
570 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, 0x15, 0x72, 0x8E,
571 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D,
572 0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF,
573 0x1C, 0xBA, 0x64, 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB,
574 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C,
575 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
576 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E,
577 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3,
578 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, 0xF1, 0x2F, 0xFA,
579 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73,
580 0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17,
581 0x7B, 0x20, 0x0C, 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61,
582 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46,
583 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
584 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B,
585 0x82, 0xD1, 0x20, 0xA9, 0x3A, 0xD2, 0xCA, 0xFF, 0xFF,
586 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
589 const gnutls_datum_t gnutls_srp_3072_group_generator = {
590 (void *) &srp3072_generator, sizeof (srp3072_generator)
593 const gnutls_datum_t gnutls_srp_3072_group_prime = {
594 (void *) srp_params_3072, sizeof (srp_params_3072)
597 static const unsigned char srp_params_4096[] = {
598 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
599 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
600 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
601 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
602 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
603 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
604 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
605 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
606 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
607 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
608 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
609 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
610 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
611 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
612 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
613 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
614 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2,
615 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
616 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C,
617 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
618 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D,
619 0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
620 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57,
621 0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
622 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0,
623 0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
624 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73,
625 0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
626 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0,
627 0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
628 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20,
629 0xA9, 0x21, 0x08, 0x01, 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
630 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, 0x99, 0xC3, 0x27, 0x18,
631 0x6A, 0xF4, 0xE2, 0x3C, 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA,
632 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, 0xDB, 0xBB, 0xC2, 0xDB,
633 0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
634 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, 0xB2, 0x96, 0x4F,
635 0xA0, 0x90, 0xC3, 0xA2, 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED,
636 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, 0xB8, 0x1B, 0xDD, 0x76,
637 0x21, 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
638 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, 0xB7, 0xDC,
639 0x90, 0xA6, 0xC0, 0x8F, 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99,
640 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
643 const gnutls_datum_t gnutls_srp_4096_group_generator = {
644 (void *) &srp3072_generator, sizeof (srp3072_generator)
647 const gnutls_datum_t gnutls_srp_4096_group_prime = {
648 (void *) srp_params_4096, sizeof (srp_params_4096)
651 /* Check if G and N are parameters from the SRP draft.
653 static int
654 check_g_n (const uint8_t * g, size_t n_g, const uint8_t * n, size_t n_n)
657 if ((n_n == sizeof (srp_params_3072) &&
658 memcmp (srp_params_3072, n, n_n) == 0) ||
659 (n_n == sizeof (srp_params_4096) &&
660 memcmp (srp_params_4096, n, n_n) == 0))
662 if (n_g != 1 || g[0] != srp3072_generator)
664 return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
666 return 0;
669 if (n_g != 1 || g[0] != srp_generator)
671 gnutls_assert ();
672 return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
675 if (n_n == sizeof (srp_params_1024) &&
676 memcmp (srp_params_1024, n, n_n) == 0)
678 return 0;
681 if (n_n == sizeof (srp_params_1536) &&
682 memcmp (srp_params_1536, n, n_n) == 0)
684 return 0;
687 if (n_n == sizeof (srp_params_2048) &&
688 memcmp (srp_params_2048, n, n_n) == 0)
690 return 0;
693 gnutls_assert ();
694 return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
697 /* Check if N is a prime and G a generator of the
698 * group. This is check only done if N is big enough.
699 * Otherwise only the included parameters must be used.
701 static int
702 group_check_g_n (gnutls_session_t session, bigint_t g, bigint_t n)
704 bigint_t q = NULL, two = NULL, w = NULL;
705 int ret;
707 if (_gnutls_mpi_get_nbits (n) < (session->internals.srp_prime_bits
708 ? session->internals.srp_prime_bits
709 : 2048))
711 gnutls_assert ();
712 return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
715 /* N must be of the form N=2q+1
716 * where q is also a prime.
718 if (_gnutls_prime_check (n) != 0)
720 _gnutls_mpi_log ("no prime N: ", n);
721 gnutls_assert ();
722 return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
725 two = _gnutls_mpi_new (4);
726 if (two == NULL)
728 gnutls_assert ();
729 return GNUTLS_E_MEMORY_ERROR;
732 q = _gnutls_mpi_alloc_like (n);
733 if (q == NULL)
735 gnutls_assert ();
736 ret = GNUTLS_E_MEMORY_ERROR;
737 goto error;
740 /* q = n-1
742 _gnutls_mpi_sub_ui (q, n, 1);
744 /* q = q/2, remember that q is divisible by 2 (prime - 1)
746 _gnutls_mpi_set_ui (two, 2);
747 _gnutls_mpi_div (q, q, two);
749 if (_gnutls_prime_check (q) != 0)
751 /* N was not on the form N=2q+1, where q = prime
753 _gnutls_mpi_log ("no prime Q: ", q);
754 gnutls_assert ();
755 return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
758 /* We also check whether g is a generator,
761 /* check if g < q < N
763 if (_gnutls_mpi_cmp (g, q) >= 0)
765 gnutls_assert ();
766 ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
767 goto error;
770 w = _gnutls_mpi_alloc_like (q);
771 if (w == NULL)
773 gnutls_assert ();
774 ret = GNUTLS_E_MEMORY_ERROR;
775 goto error;
778 /* check if g^q mod N == N-1
779 * w = g^q mod N
781 _gnutls_mpi_powm (w, g, q, n);
783 /* w++
785 _gnutls_mpi_add_ui (w, w, 1);
787 if (_gnutls_mpi_cmp (w, n) != 0)
789 gnutls_assert ();
790 ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
791 goto error;
794 ret = 0;
796 error:
797 _gnutls_mpi_release (&q);
798 _gnutls_mpi_release (&two);
799 _gnutls_mpi_release (&w);
801 return ret;
805 /* receive the key exchange message ( n, g, s, B)
808 _gnutls_proc_srp_server_kx (gnutls_session_t session, uint8_t * data,
809 size_t _data_size)
811 uint8_t n_s;
812 uint16_t n_g, n_n, n_b;
813 size_t _n_g, _n_n, _n_b;
814 const uint8_t *data_n;
815 const uint8_t *data_g;
816 const uint8_t *data_s;
817 const uint8_t *data_b;
818 int i, ret;
819 uint8_t hd[SRP_MAX_HASH_SIZE];
820 char *username, *password;
821 ssize_t data_size = _data_size;
822 gnutls_srp_client_credentials_t cred;
823 extension_priv_data_t epriv;
824 srp_ext_st *priv;
826 ret = _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_SRP, &epriv);
827 if (ret < 0)
829 gnutls_assert ();
830 return GNUTLS_E_UNKNOWN_SRP_USERNAME;
832 priv = epriv.ptr;
834 cred = (gnutls_srp_client_credentials_t)
835 _gnutls_get_cred (session->key, GNUTLS_CRD_SRP, NULL);
837 if (cred == NULL)
839 gnutls_assert ();
840 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
843 if (priv->username == NULL)
845 username = cred->username;
846 password = cred->password;
848 else
850 username = priv->username;
851 password = priv->password;
854 if (username == NULL || password == NULL)
856 gnutls_assert ();
857 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
860 i = 0;
862 /* Read N
864 DECR_LEN (data_size, 2);
865 n_n = _gnutls_read_uint16 (&data[i]);
866 i += 2;
868 DECR_LEN (data_size, n_n);
869 data_n = &data[i];
870 i += n_n;
872 /* Read G
874 DECR_LEN (data_size, 2);
875 n_g = _gnutls_read_uint16 (&data[i]);
876 i += 2;
878 DECR_LEN (data_size, n_g);
879 data_g = &data[i];
880 i += n_g;
882 /* Read salt
884 DECR_LEN (data_size, 1);
885 n_s = data[i];
886 i += 1;
888 DECR_LEN (data_size, n_s);
889 data_s = &data[i];
890 i += n_s;
892 /* Read B
894 DECR_LEN (data_size, 2);
895 n_b = _gnutls_read_uint16 (&data[i]);
896 i += 2;
898 DECR_LEN (data_size, n_b);
899 data_b = &data[i];
900 i += n_b;
902 _n_g = n_g;
903 _n_n = n_n;
904 _n_b = n_b;
906 if (_gnutls_mpi_scan_nz (&N, data_n, _n_n) != 0)
908 gnutls_assert ();
909 return GNUTLS_E_MPI_SCAN_FAILED;
912 if (_gnutls_mpi_scan_nz (&G, data_g, _n_g) != 0)
914 gnutls_assert ();
915 return GNUTLS_E_MPI_SCAN_FAILED;
918 if (_gnutls_mpi_scan_nz (&B, data_b, _n_b) != 0)
920 gnutls_assert ();
921 return GNUTLS_E_MPI_SCAN_FAILED;
925 /* Check if the g and n are from the SRP
926 * draft. Otherwise check if N is a prime and G
927 * a generator.
929 if ((ret = check_g_n (data_g, _n_g, data_n, _n_n)) < 0)
931 _gnutls_audit_log (session, "SRP group parameters are not in the white list. Checking validity.\n");
932 if ((ret = group_check_g_n (session, G, N)) < 0)
934 gnutls_assert ();
935 return ret;
939 /* Checks if b % n == 0
941 if ((ret = check_b_mod_n (B, N)) < 0)
943 gnutls_assert ();
944 return ret;
948 /* generate x = SHA(s | SHA(U | ":" | p))
949 * (or the equivalent using bcrypt)
951 if ((ret =
952 _gnutls_calc_srp_x (username, password, (uint8_t *) data_s, n_s,
953 &_n_g, hd)) < 0)
955 gnutls_assert ();
956 return ret;
959 if (_gnutls_mpi_scan_nz (&session->key->x, hd, _n_g) != 0)
961 gnutls_assert ();
962 return GNUTLS_E_MPI_SCAN_FAILED;
966 return i; /* return the processed data
967 * needed in auth_srp_rsa.
971 #endif /* ENABLE_SRP */