enable useful extensions in the examples.
[gnutls.git] / lib / auth / srp.c
blob835c87162bd59b170712ffe93c8706627678fc8e
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 a%n==0,+1,-1%n 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_param_mod_n (bigint_t a, bigint_t n, int is_a)
72 int ret, err = 0;
73 bigint_t r;
75 r = _gnutls_mpi_mod (a, n);
76 if (r == NULL)
78 gnutls_assert ();
79 return GNUTLS_E_MEMORY_ERROR;
82 ret = _gnutls_mpi_cmp_ui (r, 0);
83 if (ret == 0) err = 1;
85 if (is_a != 0)
87 ret = _gnutls_mpi_cmp_ui (r, 1);
88 if (ret == 0) err = 1;
90 _gnutls_mpi_add_ui(r, r, 1);
91 ret = _gnutls_mpi_cmp (r, n);
92 if (ret == 0) err = 1;
95 _gnutls_mpi_release (&r);
97 if (err != 0)
99 gnutls_assert ();
100 return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
103 return 0;
107 /* Send the first key exchange message ( g, n, s) and append the verifier algorithm number
108 * Data is allocated by the caller, and should have data_size size.
111 _gnutls_gen_srp_server_kx (gnutls_session_t session, gnutls_buffer_st* data)
113 int ret;
114 char *username;
115 SRP_PWD_ENTRY *pwd_entry;
116 srp_server_auth_info_t info;
117 size_t tmp_size;
118 extension_priv_data_t epriv;
119 srp_ext_st *priv;
121 ret = _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_SRP, &epriv);
122 if (ret < 0) /* peer didn't send a username */
124 gnutls_assert ();
125 return GNUTLS_E_UNKNOWN_SRP_USERNAME;
127 priv = epriv.ptr;
129 if ((ret =
130 _gnutls_auth_info_set (session, GNUTLS_CRD_SRP,
131 sizeof (srp_server_auth_info_st), 1)) < 0)
133 gnutls_assert ();
134 return ret;
137 info = _gnutls_get_auth_info (session);
138 username = info->username;
140 _gnutls_str_cpy (username, MAX_USERNAME_SIZE, priv->username);
142 ret = _gnutls_srp_pwd_read_entry (session, username, &pwd_entry);
144 if (ret < 0)
146 gnutls_assert ();
147 return ret;
150 /* copy from pwd_entry to local variables (actually in session) */
151 tmp_size = pwd_entry->g.size;
152 if (_gnutls_mpi_scan_nz (&G, pwd_entry->g.data, tmp_size) < 0)
154 gnutls_assert ();
155 ret = GNUTLS_E_MPI_SCAN_FAILED;
156 goto cleanup;
159 tmp_size = pwd_entry->n.size;
160 if (_gnutls_mpi_scan_nz (&N, pwd_entry->n.data, tmp_size) < 0)
162 gnutls_assert ();
163 ret = GNUTLS_E_MPI_SCAN_FAILED;
164 goto cleanup;
167 tmp_size = pwd_entry->v.size;
168 if (_gnutls_mpi_scan_nz (&V, pwd_entry->v.data, tmp_size) < 0)
170 gnutls_assert ();
171 ret = GNUTLS_E_MPI_SCAN_FAILED;
172 goto cleanup;
175 /* Calculate: B = (k*v + g^b) % N
177 B = _gnutls_calc_srp_B (&_b, G, N, V);
178 if (B == NULL)
180 gnutls_assert ();
181 ret = GNUTLS_E_MEMORY_ERROR;
182 goto cleanup;
185 /* copy N (mod n)
187 ret = _gnutls_buffer_append_data_prefix( data, 16, pwd_entry->n.data,
188 pwd_entry->n.size);
189 if (ret < 0)
191 gnutls_assert();
192 goto cleanup;
195 /* copy G (generator) to data
197 ret = _gnutls_buffer_append_data_prefix( data, 16, pwd_entry->g.data,
198 pwd_entry->g.size);
199 if (ret < 0)
201 gnutls_assert();
202 goto cleanup;
205 /* copy the salt
207 ret = _gnutls_buffer_append_data_prefix( data, 8, pwd_entry->salt.data,
208 pwd_entry->salt.size);
209 if (ret < 0)
211 gnutls_assert();
212 goto cleanup;
215 /* Copy the B value
218 ret = _gnutls_buffer_append_mpi( data, 16, B, 0);
219 if (ret < 0)
221 gnutls_assert();
222 goto cleanup;
225 _gnutls_mpi_log ("SRP B: ", B);
227 ret = data->length;
229 cleanup:
230 _gnutls_srp_entry_free (pwd_entry);
231 return ret;
234 /* return A = g^a % N */
236 _gnutls_gen_srp_client_kx (gnutls_session_t session, gnutls_buffer_st* data)
238 int ret;
239 char *username, *password;
240 gnutls_srp_client_credentials_t cred;
241 extension_priv_data_t epriv;
242 srp_ext_st *priv;
244 ret = _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_SRP, &epriv);
245 if (ret < 0) /* peer didn't send a username */
247 gnutls_assert ();
248 return GNUTLS_E_UNKNOWN_SRP_USERNAME;
250 priv = epriv.ptr;
252 cred = (gnutls_srp_client_credentials_t)
253 _gnutls_get_cred (session->key, GNUTLS_CRD_SRP, NULL);
255 if (cred == NULL)
257 gnutls_assert ();
258 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
261 if (priv->username == NULL)
263 username = cred->username;
264 password = cred->password;
266 else
269 username = priv->username;
270 password = priv->password;
273 if (username == NULL || password == NULL)
275 gnutls_assert ();
276 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
279 /* calc A = g^a % N
281 if (G == NULL || N == NULL)
283 gnutls_assert ();
284 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
287 A = _gnutls_calc_srp_A (&_a, G, N);
288 if (A == NULL)
290 gnutls_assert ();
291 return GNUTLS_E_MEMORY_ERROR;
294 /* Rest of SRP calculations
297 /* calculate u */
298 session->key->u = _gnutls_calc_srp_u (A, B, N);
299 if (session->key->u == NULL)
301 gnutls_assert ();
302 return GNUTLS_E_MEMORY_ERROR;
305 _gnutls_mpi_log ("SRP U: ", session->key->u);
307 /* S = (B - g^x) ^ (a + u * x) % N */
308 S = _gnutls_calc_srp_S2 (B, G, session->key->x, _a, session->key->u, N);
309 if (S == NULL)
311 gnutls_assert ();
312 return GNUTLS_E_MEMORY_ERROR;
315 _gnutls_mpi_log ("SRP B: ", B);
317 _gnutls_mpi_release (&_b);
318 _gnutls_mpi_release (&V);
319 _gnutls_mpi_release (&session->key->u);
320 _gnutls_mpi_release (&B);
322 ret = _gnutls_mpi_dprint (session->key->KEY, &session->key->key);
323 _gnutls_mpi_release (&S);
325 if (ret < 0)
327 gnutls_assert ();
328 return ret;
331 ret = _gnutls_buffer_append_mpi(data, 16, A, 0);
332 if (ret < 0)
333 return gnutls_assert_val(ret);
335 _gnutls_mpi_log ("SRP A: ", A);
337 _gnutls_mpi_release (&A);
339 return data->length;
343 /* just read A and put it to session */
345 _gnutls_proc_srp_client_kx (gnutls_session_t session, uint8_t * data,
346 size_t _data_size)
348 size_t _n_A;
349 ssize_t data_size = _data_size;
350 int ret;
352 DECR_LEN (data_size, 2);
353 _n_A = _gnutls_read_uint16 (&data[0]);
355 DECR_LEN (data_size, _n_A);
356 if (_gnutls_mpi_scan_nz (&A, &data[2], _n_A) || A == NULL)
358 gnutls_assert ();
359 return GNUTLS_E_MPI_SCAN_FAILED;
362 _gnutls_mpi_log ("SRP A: ", A);
363 _gnutls_mpi_log ("SRP B: ", B);
365 /* Checks if A % n == 0.
367 if ((ret = check_param_mod_n (A, N, 1)) < 0)
369 gnutls_assert ();
370 return ret;
373 /* Start the SRP calculations.
374 * - Calculate u
376 session->key->u = _gnutls_calc_srp_u (A, B, N);
377 if (session->key->u == NULL)
379 gnutls_assert ();
380 return GNUTLS_E_MEMORY_ERROR;
383 _gnutls_mpi_log ("SRP U: ", session->key->u);
385 /* S = (A * v^u) ^ b % N
387 S = _gnutls_calc_srp_S1 (A, _b, session->key->u, V, N);
388 if (S == NULL)
390 gnutls_assert ();
391 return GNUTLS_E_MEMORY_ERROR;
394 _gnutls_mpi_log ("SRP S: ", S);
396 _gnutls_mpi_release (&A);
397 _gnutls_mpi_release (&_b);
398 _gnutls_mpi_release (&V);
399 _gnutls_mpi_release (&session->key->u);
400 _gnutls_mpi_release (&B);
402 ret = _gnutls_mpi_dprint (session->key->KEY, &session->key->key);
403 _gnutls_mpi_release (&S);
405 if (ret < 0)
407 gnutls_assert ();
408 return ret;
411 return 0;
416 /* Static parameters according to draft-ietf-tls-srp-07
417 * Note that if more parameters are added check_g_n()
418 * and _gnutls_srp_entry_free() should be changed.
420 static const unsigned char srp_params_1024[] = {
421 0xEE, 0xAF, 0x0A, 0xB9, 0xAD, 0xB3, 0x8D, 0xD6,
422 0x9C, 0x33, 0xF8, 0x0A, 0xFA, 0x8F, 0xC5, 0xE8,
423 0x60, 0x72, 0x61, 0x87, 0x75, 0xFF, 0x3C, 0x0B,
424 0x9E, 0xA2, 0x31, 0x4C, 0x9C, 0x25, 0x65, 0x76,
425 0xD6, 0x74, 0xDF, 0x74, 0x96, 0xEA, 0x81, 0xD3,
426 0x38, 0x3B, 0x48, 0x13, 0xD6, 0x92, 0xC6, 0xE0,
427 0xE0, 0xD5, 0xD8, 0xE2, 0x50, 0xB9, 0x8B, 0xE4,
428 0x8E, 0x49, 0x5C, 0x1D, 0x60, 0x89, 0xDA, 0xD1,
429 0x5D, 0xC7, 0xD7, 0xB4, 0x61, 0x54, 0xD6, 0xB6,
430 0xCE, 0x8E, 0xF4, 0xAD, 0x69, 0xB1, 0x5D, 0x49,
431 0x82, 0x55, 0x9B, 0x29, 0x7B, 0xCF, 0x18, 0x85,
432 0xC5, 0x29, 0xF5, 0x66, 0x66, 0x0E, 0x57, 0xEC,
433 0x68, 0xED, 0xBC, 0x3C, 0x05, 0x72, 0x6C, 0xC0,
434 0x2F, 0xD4, 0xCB, 0xF4, 0x97, 0x6E, 0xAA, 0x9A,
435 0xFD, 0x51, 0x38, 0xFE, 0x83, 0x76, 0x43, 0x5B,
436 0x9F, 0xC6, 0x1D, 0x2F, 0xC0, 0xEB, 0x06, 0xE3
439 static const unsigned char srp_generator = 0x02;
440 static const unsigned char srp3072_generator = 0x05;
442 const gnutls_datum_t gnutls_srp_1024_group_prime = {
443 (void *) srp_params_1024, sizeof (srp_params_1024)
446 const gnutls_datum_t gnutls_srp_1024_group_generator = {
447 (void *) &srp_generator, sizeof (srp_generator)
450 static const unsigned char srp_params_1536[] = {
451 0x9D, 0xEF, 0x3C, 0xAF, 0xB9, 0x39, 0x27, 0x7A, 0xB1,
452 0xF1, 0x2A, 0x86, 0x17, 0xA4, 0x7B, 0xBB, 0xDB, 0xA5,
453 0x1D, 0xF4, 0x99, 0xAC, 0x4C, 0x80, 0xBE, 0xEE, 0xA9,
454 0x61, 0x4B, 0x19, 0xCC, 0x4D, 0x5F, 0x4F, 0x5F, 0x55,
455 0x6E, 0x27, 0xCB, 0xDE, 0x51, 0xC6, 0xA9, 0x4B, 0xE4,
456 0x60, 0x7A, 0x29, 0x15, 0x58, 0x90, 0x3B, 0xA0, 0xD0,
457 0xF8, 0x43, 0x80, 0xB6, 0x55, 0xBB, 0x9A, 0x22, 0xE8,
458 0xDC, 0xDF, 0x02, 0x8A, 0x7C, 0xEC, 0x67, 0xF0, 0xD0,
459 0x81, 0x34, 0xB1, 0xC8, 0xB9, 0x79, 0x89, 0x14, 0x9B,
460 0x60, 0x9E, 0x0B, 0xE3, 0xBA, 0xB6, 0x3D, 0x47, 0x54,
461 0x83, 0x81, 0xDB, 0xC5, 0xB1, 0xFC, 0x76, 0x4E, 0x3F,
462 0x4B, 0x53, 0xDD, 0x9D, 0xA1, 0x15, 0x8B, 0xFD, 0x3E,
463 0x2B, 0x9C, 0x8C, 0xF5, 0x6E, 0xDF, 0x01, 0x95, 0x39,
464 0x34, 0x96, 0x27, 0xDB, 0x2F, 0xD5, 0x3D, 0x24, 0xB7,
465 0xC4, 0x86, 0x65, 0x77, 0x2E, 0x43, 0x7D, 0x6C, 0x7F,
466 0x8C, 0xE4, 0x42, 0x73, 0x4A, 0xF7, 0xCC, 0xB7, 0xAE,
467 0x83, 0x7C, 0x26, 0x4A, 0xE3, 0xA9, 0xBE, 0xB8, 0x7F,
468 0x8A, 0x2F, 0xE9, 0xB8, 0xB5, 0x29, 0x2E, 0x5A, 0x02,
469 0x1F, 0xFF, 0x5E, 0x91, 0x47, 0x9E, 0x8C, 0xE7, 0xA2,
470 0x8C, 0x24, 0x42, 0xC6, 0xF3, 0x15, 0x18, 0x0F, 0x93,
471 0x49, 0x9A, 0x23, 0x4D, 0xCF, 0x76, 0xE3, 0xFE, 0xD1,
472 0x35, 0xF9, 0xBB
475 const gnutls_datum_t gnutls_srp_1536_group_prime = {
476 (void *) srp_params_1536, sizeof (srp_params_1536)
479 const gnutls_datum_t gnutls_srp_1536_group_generator = {
480 (void *) &srp_generator, sizeof (srp_generator)
483 static const unsigned char srp_params_2048[] = {
484 0xAC, 0x6B, 0xDB, 0x41, 0x32, 0x4A, 0x9A, 0x9B, 0xF1,
485 0x66, 0xDE, 0x5E, 0x13, 0x89, 0x58, 0x2F, 0xAF, 0x72,
486 0xB6, 0x65, 0x19, 0x87, 0xEE, 0x07, 0xFC, 0x31, 0x92,
487 0x94, 0x3D, 0xB5, 0x60, 0x50, 0xA3, 0x73, 0x29, 0xCB,
488 0xB4, 0xA0, 0x99, 0xED, 0x81, 0x93, 0xE0, 0x75, 0x77,
489 0x67, 0xA1, 0x3D, 0xD5, 0x23, 0x12, 0xAB, 0x4B, 0x03,
490 0x31, 0x0D, 0xCD, 0x7F, 0x48, 0xA9, 0xDA, 0x04, 0xFD,
491 0x50, 0xE8, 0x08, 0x39, 0x69, 0xED, 0xB7, 0x67, 0xB0,
492 0xCF, 0x60, 0x95, 0x17, 0x9A, 0x16, 0x3A, 0xB3, 0x66,
493 0x1A, 0x05, 0xFB, 0xD5, 0xFA, 0xAA, 0xE8, 0x29, 0x18,
494 0xA9, 0x96, 0x2F, 0x0B, 0x93, 0xB8, 0x55, 0xF9, 0x79,
495 0x93, 0xEC, 0x97, 0x5E, 0xEA, 0xA8, 0x0D, 0x74, 0x0A,
496 0xDB, 0xF4, 0xFF, 0x74, 0x73, 0x59, 0xD0, 0x41, 0xD5,
497 0xC3, 0x3E, 0xA7, 0x1D, 0x28, 0x1E, 0x44, 0x6B, 0x14,
498 0x77, 0x3B, 0xCA, 0x97, 0xB4, 0x3A, 0x23, 0xFB, 0x80,
499 0x16, 0x76, 0xBD, 0x20, 0x7A, 0x43, 0x6C, 0x64, 0x81,
500 0xF1, 0xD2, 0xB9, 0x07, 0x87, 0x17, 0x46, 0x1A, 0x5B,
501 0x9D, 0x32, 0xE6, 0x88, 0xF8, 0x77, 0x48, 0x54, 0x45,
502 0x23, 0xB5, 0x24, 0xB0, 0xD5, 0x7D, 0x5E, 0xA7, 0x7A,
503 0x27, 0x75, 0xD2, 0xEC, 0xFA, 0x03, 0x2C, 0xFB, 0xDB,
504 0xF5, 0x2F, 0xB3, 0x78, 0x61, 0x60, 0x27, 0x90, 0x04,
505 0xE5, 0x7A, 0xE6, 0xAF, 0x87, 0x4E, 0x73, 0x03, 0xCE,
506 0x53, 0x29, 0x9C, 0xCC, 0x04, 0x1C, 0x7B, 0xC3, 0x08,
507 0xD8, 0x2A, 0x56, 0x98, 0xF3, 0xA8, 0xD0, 0xC3, 0x82,
508 0x71, 0xAE, 0x35, 0xF8, 0xE9, 0xDB, 0xFB, 0xB6, 0x94,
509 0xB5, 0xC8, 0x03, 0xD8, 0x9F, 0x7A, 0xE4, 0x35, 0xDE,
510 0x23, 0x6D, 0x52, 0x5F, 0x54, 0x75, 0x9B, 0x65, 0xE3,
511 0x72, 0xFC, 0xD6, 0x8E, 0xF2, 0x0F, 0xA7, 0x11, 0x1F,
512 0x9E, 0x4A, 0xFF, 0x73
515 const gnutls_datum_t gnutls_srp_2048_group_prime = {
516 (void *) srp_params_2048, sizeof (srp_params_2048)
519 const gnutls_datum_t gnutls_srp_2048_group_generator = {
520 (void *) &srp_generator, sizeof (srp_generator)
523 static const unsigned char srp_params_3072[] = {
524 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9,
525 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6,
526 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E,
527 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
528 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E,
529 0x34, 0x04, 0xDD, 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A,
530 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14,
531 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
532 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4,
533 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF,
534 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, 0xEE, 0x38, 0x6B,
535 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
536 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC,
537 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63,
538 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3,
539 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
540 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C,
541 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5,
542 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35,
543 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
544 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E,
545 0x36, 0xCE, 0x3B, 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E,
546 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2,
547 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
548 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39,
549 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2,
550 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, 0x15, 0x72, 0x8E,
551 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D,
552 0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF,
553 0x1C, 0xBA, 0x64, 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB,
554 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C,
555 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
556 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E,
557 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3,
558 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, 0xF1, 0x2F, 0xFA,
559 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73,
560 0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17,
561 0x7B, 0x20, 0x0C, 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61,
562 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46,
563 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
564 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B,
565 0x82, 0xD1, 0x20, 0xA9, 0x3A, 0xD2, 0xCA, 0xFF, 0xFF,
566 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
569 const gnutls_datum_t gnutls_srp_3072_group_generator = {
570 (void *) &srp3072_generator, sizeof (srp3072_generator)
573 const gnutls_datum_t gnutls_srp_3072_group_prime = {
574 (void *) srp_params_3072, sizeof (srp_params_3072)
577 static const unsigned char srp_params_4096[] = {
578 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
579 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
580 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
581 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
582 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
583 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
584 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
585 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
586 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
587 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
588 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
589 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
590 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
591 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
592 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
593 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
594 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2,
595 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
596 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C,
597 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
598 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D,
599 0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
600 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57,
601 0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
602 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0,
603 0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
604 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73,
605 0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
606 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0,
607 0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
608 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20,
609 0xA9, 0x21, 0x08, 0x01, 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
610 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, 0x99, 0xC3, 0x27, 0x18,
611 0x6A, 0xF4, 0xE2, 0x3C, 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA,
612 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, 0xDB, 0xBB, 0xC2, 0xDB,
613 0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
614 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, 0xB2, 0x96, 0x4F,
615 0xA0, 0x90, 0xC3, 0xA2, 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED,
616 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, 0xB8, 0x1B, 0xDD, 0x76,
617 0x21, 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
618 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, 0xB7, 0xDC,
619 0x90, 0xA6, 0xC0, 0x8F, 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99,
620 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
623 const gnutls_datum_t gnutls_srp_4096_group_generator = {
624 (void *) &srp3072_generator, sizeof (srp3072_generator)
627 const gnutls_datum_t gnutls_srp_4096_group_prime = {
628 (void *) srp_params_4096, sizeof (srp_params_4096)
631 /* Check if G and N are parameters from the SRP draft.
633 static int
634 check_g_n (const uint8_t * g, size_t n_g, const uint8_t * n, size_t n_n)
637 if ((n_n == sizeof (srp_params_3072) &&
638 memcmp (srp_params_3072, n, n_n) == 0) ||
639 (n_n == sizeof (srp_params_4096) &&
640 memcmp (srp_params_4096, n, n_n) == 0))
642 if (n_g != 1 || g[0] != srp3072_generator)
644 return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
646 return 0;
649 if (n_g != 1 || g[0] != srp_generator)
651 gnutls_assert ();
652 return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
655 if (n_n == sizeof (srp_params_1024) &&
656 memcmp (srp_params_1024, n, n_n) == 0)
658 return 0;
661 if (n_n == sizeof (srp_params_1536) &&
662 memcmp (srp_params_1536, n, n_n) == 0)
664 return 0;
667 if (n_n == sizeof (srp_params_2048) &&
668 memcmp (srp_params_2048, n, n_n) == 0)
670 return 0;
673 gnutls_assert ();
674 return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
677 /* Check if N is a prime and G a generator of the
678 * group. This check is only done if N is big enough.
679 * Otherwise only the included parameters must be used.
681 static int
682 group_check_g_n (gnutls_session_t session, bigint_t g, bigint_t n)
684 bigint_t q = NULL, two = NULL, w = NULL;
685 int ret;
687 if (_gnutls_mpi_get_nbits (n) < (session->internals.srp_prime_bits
688 ? session->internals.srp_prime_bits
689 : 2048))
691 gnutls_assert ();
692 return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
695 /* N must be of the form N=2q+1
696 * where q is also a prime.
698 if (_gnutls_prime_check (n) != 0)
700 _gnutls_mpi_log ("no prime N: ", n);
701 gnutls_assert ();
702 return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
705 two = _gnutls_mpi_new (4);
706 if (two == NULL)
708 gnutls_assert ();
709 return GNUTLS_E_MEMORY_ERROR;
712 q = _gnutls_mpi_alloc_like (n);
713 if (q == NULL)
715 gnutls_assert ();
716 ret = GNUTLS_E_MEMORY_ERROR;
717 goto error;
720 /* q = n-1
722 _gnutls_mpi_sub_ui (q, n, 1);
724 /* q = q/2, remember that q is divisible by 2 (prime - 1)
726 _gnutls_mpi_set_ui (two, 2);
727 _gnutls_mpi_div (q, q, two);
729 if (_gnutls_prime_check (q) != 0)
731 /* N was not on the form N=2q+1, where q = prime
733 _gnutls_mpi_log ("no prime Q: ", q);
734 gnutls_assert ();
735 return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
738 /* We also check whether g is a generator,
741 /* check if g < q < N
743 if (_gnutls_mpi_cmp (g, q) >= 0)
745 gnutls_assert ();
746 ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
747 goto error;
750 w = _gnutls_mpi_alloc_like (q);
751 if (w == NULL)
753 gnutls_assert ();
754 ret = GNUTLS_E_MEMORY_ERROR;
755 goto error;
758 /* check if g^q mod N == N-1
759 * w = g^q mod N
761 _gnutls_mpi_powm (w, g, q, n);
763 /* w++
765 _gnutls_mpi_add_ui (w, w, 1);
767 if (_gnutls_mpi_cmp (w, n) != 0)
769 gnutls_assert ();
770 ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
771 goto error;
774 ret = 0;
776 error:
777 _gnutls_mpi_release (&q);
778 _gnutls_mpi_release (&two);
779 _gnutls_mpi_release (&w);
781 return ret;
785 /* receive the key exchange message ( n, g, s, B)
788 _gnutls_proc_srp_server_kx (gnutls_session_t session, uint8_t * data,
789 size_t _data_size)
791 uint8_t n_s;
792 uint16_t n_g, n_n, n_b;
793 size_t _n_g, _n_n, _n_b;
794 const uint8_t *data_n;
795 const uint8_t *data_g;
796 const uint8_t *data_s;
797 const uint8_t *data_b;
798 int i, ret;
799 uint8_t hd[SRP_MAX_HASH_SIZE];
800 char *username, *password;
801 ssize_t data_size = _data_size;
802 gnutls_srp_client_credentials_t cred;
803 extension_priv_data_t epriv;
804 srp_ext_st *priv;
806 ret = _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_SRP, &epriv);
807 if (ret < 0)
809 gnutls_assert ();
810 return GNUTLS_E_UNKNOWN_SRP_USERNAME;
812 priv = epriv.ptr;
814 cred = (gnutls_srp_client_credentials_t)
815 _gnutls_get_cred (session->key, GNUTLS_CRD_SRP, NULL);
817 if (cred == NULL)
819 gnutls_assert ();
820 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
823 if (priv->username == NULL)
825 username = cred->username;
826 password = cred->password;
828 else
830 username = priv->username;
831 password = priv->password;
834 if (username == NULL || password == NULL)
836 gnutls_assert ();
837 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
840 i = 0;
842 /* Read N
844 DECR_LEN (data_size, 2);
845 n_n = _gnutls_read_uint16 (&data[i]);
846 i += 2;
848 DECR_LEN (data_size, n_n);
849 data_n = &data[i];
850 i += n_n;
852 /* Read G
854 DECR_LEN (data_size, 2);
855 n_g = _gnutls_read_uint16 (&data[i]);
856 i += 2;
858 DECR_LEN (data_size, n_g);
859 data_g = &data[i];
860 i += n_g;
862 /* Read salt
864 DECR_LEN (data_size, 1);
865 n_s = data[i];
866 i += 1;
868 DECR_LEN (data_size, n_s);
869 data_s = &data[i];
870 i += n_s;
872 /* Read B
874 DECR_LEN (data_size, 2);
875 n_b = _gnutls_read_uint16 (&data[i]);
876 i += 2;
878 DECR_LEN (data_size, n_b);
879 data_b = &data[i];
880 i += n_b;
882 _n_g = n_g;
883 _n_n = n_n;
884 _n_b = n_b;
886 if (_gnutls_mpi_scan_nz (&N, data_n, _n_n) != 0)
888 gnutls_assert ();
889 return GNUTLS_E_MPI_SCAN_FAILED;
892 if (_gnutls_mpi_scan_nz (&G, data_g, _n_g) != 0)
894 gnutls_assert ();
895 return GNUTLS_E_MPI_SCAN_FAILED;
898 if (_gnutls_mpi_scan_nz (&B, data_b, _n_b) != 0)
900 gnutls_assert ();
901 return GNUTLS_E_MPI_SCAN_FAILED;
905 /* Check if the g and n are from the SRP
906 * draft. Otherwise check if N is a prime and G
907 * a generator.
909 if ((ret = check_g_n (data_g, _n_g, data_n, _n_n)) < 0)
911 _gnutls_audit_log (session, "SRP group parameters are not in the white list. Checking validity.\n");
912 if ((ret = group_check_g_n (session, G, N)) < 0)
914 gnutls_assert ();
915 return ret;
919 /* Checks if b % n == 0
921 if ((ret = check_param_mod_n (B, N, 0)) < 0)
923 gnutls_assert ();
924 return ret;
928 /* generate x = SHA(s | SHA(U | ":" | p))
929 * (or the equivalent using bcrypt)
931 if ((ret =
932 _gnutls_calc_srp_x (username, password, (uint8_t *) data_s, n_s,
933 &_n_g, hd)) < 0)
935 gnutls_assert ();
936 return ret;
939 if (_gnutls_mpi_scan_nz (&session->key->x, hd, _n_g) != 0)
941 gnutls_assert ();
942 return GNUTLS_E_MPI_SCAN_FAILED;
946 return i; /* return the processed data
947 * needed in auth_srp_rsa.
951 #endif /* ENABLE_SRP */