*** empty log message ***
[gnutls.git] / libextra / auth_srp.c
blob89b7b36fcb7a56d8d448761e42b63d78f358e0b8
1 /*
2 * Copyright (C) 2001,2002 Nikos Mavroyanopoulos
4 * This file is part of GNUTLS.
6 * GNUTLS-EXTRA is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * GNUTLS-EXTRA is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
21 #include "gnutls_int.h"
23 #ifdef ENABLE_SRP
25 #include "gnutls_errors.h"
26 #include "auth_srp_passwd.h"
27 #include "gnutls_auth.h"
28 #include "gnutls_auth_int.h"
29 #include "gnutls_srp.h"
30 #include "debug.h"
31 #include "gnutls_num.h"
32 #include "auth_srp.h"
33 #include <gnutls_str.h>
35 int gen_srp_server_kx2(GNUTLS_STATE, opaque **);
36 int gen_srp_client_kx0(GNUTLS_STATE, opaque **);
38 int proc_srp_server_kx2(GNUTLS_STATE, opaque *, int);
39 int proc_srp_client_kx0(GNUTLS_STATE, opaque *, int);
41 const MOD_AUTH_STRUCT srp_auth_struct = {
42 "SRP",
43 NULL,
44 NULL,
45 NULL,
46 gen_srp_server_kx2,
47 gen_srp_client_kx0,
48 NULL,
49 NULL,
50 NULL,
52 NULL,
53 NULL, /* certificate */
54 NULL,
55 proc_srp_server_kx2,
56 proc_srp_client_kx0,
57 NULL,
58 NULL,
59 NULL
63 #define _b state->gnutls_key->b
64 #define B state->gnutls_key->B
65 #define _a state->gnutls_key->a
66 #define A state->gnutls_key->A
67 #define N state->gnutls_key->client_p
68 #define G state->gnutls_key->client_g
69 #define V state->gnutls_key->x
70 #define S state->gnutls_key->KEY
72 /* Send the first key exchange message ( g, n, s) and append the verifier algorithm number
73 * Data is allocated by the caller, and should have data_size size.
75 int gen_srp_server_hello(GNUTLS_STATE state, opaque * data, int data_size)
77 size_t n_g, n_n, n_s;
78 size_t ret;
79 uint8 *data_n, *data_s;
80 uint8 *data_g, *username;
81 uint8 pwd_algo;
82 GNUTLS_SRP_PWD_ENTRY *pwd_entry;
83 int err;
84 SRP_SERVER_AUTH_INFO info;
86 if ( (ret=_gnutls_auth_info_set( state, GNUTLS_CRD_SRP, sizeof( SRP_SERVER_AUTH_INFO_INT), 1)) < 0) {
87 gnutls_assert();
88 return ret;
91 info = _gnutls_get_auth_info( state);
92 username = info->username;
94 _gnutls_str_cpy( username, MAX_SRP_USERNAME, state->security_parameters.extensions.srp_username);
96 pwd_entry = _gnutls_srp_pwd_read_entry( state, username, &err);
98 if (pwd_entry == NULL) {
99 if (err==0)
100 /* in order to avoid informing the peer that
101 * username does not exist.
103 pwd_entry = _gnutls_randomize_pwd_entry();
104 else
105 return GNUTLS_E_PWD_ERROR;
108 pwd_algo = (uint8) pwd_entry->algorithm;
110 if (_gnutls_mpi_print( NULL, &n_g, pwd_entry->g)!=0) {
111 gnutls_assert();
112 return GNUTLS_E_MPI_PRINT_FAILED;
114 if (_gnutls_mpi_print( NULL, &n_n, pwd_entry->n)!=0) {
115 gnutls_assert();
116 return GNUTLS_E_MPI_PRINT_FAILED;
119 /* copy from pwd_entry to local variables (actually in state) */
120 G = _gnutls_mpi_alloc_like(pwd_entry->g);
121 N = _gnutls_mpi_alloc_like(pwd_entry->n);
122 V = _gnutls_mpi_alloc_like(pwd_entry->v);
124 if (G==NULL || N == NULL || V == NULL) {
125 gnutls_assert();
126 return GNUTLS_E_MEMORY_ERROR;
129 _gnutls_mpi_set(G, pwd_entry->g);
130 _gnutls_mpi_set(N, pwd_entry->n);
131 _gnutls_mpi_set(V, pwd_entry->v);
133 if (data_size < n_n + n_g + pwd_entry->salt_size + 6 + 1) {
134 gnutls_assert();
135 return GNUTLS_E_INVALID_REQUEST;
138 data_g = data;
140 /* firstly copy the algorithm used to generate the verifier
142 data_g[0] = pwd_algo;
144 /* copy G (generator) to data */
146 data_g++;
148 if(_gnutls_mpi_print( &data_g[2], &n_g, G)!=0) {
149 gnutls_assert();
150 return GNUTLS_E_MPI_PRINT_FAILED;
153 _gnutls_write_uint16( n_g, data_g);
155 /* copy N (mod n) */
156 data_n = &data_g[2 + n_g];
158 if (_gnutls_mpi_print( &data_n[2], &n_n, N)!=0) {
159 gnutls_assert();
160 return GNUTLS_E_MPI_PRINT_FAILED;
163 _gnutls_write_uint16( n_n, data_n);
165 /* copy the salt */
166 data_s = &data_n[2 + n_n];
167 n_s = pwd_entry->salt_size;
168 memcpy(&data_s[2], pwd_entry->salt, n_s);
170 _gnutls_write_uint16( n_s, data_s);
172 ret = n_g + n_n + pwd_entry->salt_size + 6 + 1;
173 _gnutls_srp_clear_pwd_entry( pwd_entry);
175 return ret;
178 /* send the second key exchange message */
179 int gen_srp_server_kx2(GNUTLS_STATE state, opaque ** data)
181 int ret;
182 size_t n_b;
183 uint8 *data_b;
185 /* calculate: B = (v + g^b) % N */
186 B = _gnutls_calc_srp_B( &_b, G, N, V);
187 if (B==NULL) {
188 gnutls_assert();
189 return GNUTLS_E_MEMORY_ERROR;
192 if (_gnutls_mpi_print( NULL, &n_b, B)!=0)
193 return GNUTLS_E_MPI_PRINT_FAILED;
195 (*data) = gnutls_malloc(n_b + 2);
196 if ( (*data) == NULL) {
197 gnutls_assert();
198 return GNUTLS_E_MEMORY_ERROR;
201 /* copy B */
202 data_b = (*data);
203 if (_gnutls_mpi_print( &data_b[2], &n_b, B)!=0)
204 return GNUTLS_E_MPI_PRINT_FAILED;
206 _gnutls_write_uint16( n_b, data_b);
208 /* calculate u */
209 state->gnutls_key->u = _gnutls_calc_srp_u(B);
210 if (state->gnutls_key->u==NULL) {
211 gnutls_assert();
212 gnutls_free( *data);
213 return GNUTLS_E_MEMORY_ERROR;
216 /* S = (A * v^u) ^ b % N */
217 S = _gnutls_calc_srp_S1( A, _b, state->gnutls_key->u, V, N);
218 if ( S==NULL) {
219 gnutls_assert();
220 gnutls_free( *data);
221 return GNUTLS_E_MEMORY_ERROR;
224 _gnutls_mpi_release(&A);
225 _gnutls_mpi_release(&_b);
226 _gnutls_mpi_release(&V);
227 _gnutls_mpi_release(&state->gnutls_key->u);
228 _gnutls_mpi_release(&B);
230 ret = _gnutls_generate_key( state->gnutls_key);
231 _gnutls_mpi_release( &S);
233 if (ret < 0)
234 return ret;
236 return n_b + 2;
240 /* return A = g^a % N */
241 int gen_srp_client_kx0(GNUTLS_STATE state, opaque ** data)
243 size_t n_a;
244 uint8 *data_a;
245 char *username;
246 char *password;
247 const GNUTLS_SRP_CLIENT_CREDENTIALS cred =
248 _gnutls_get_cred(state->gnutls_key, GNUTLS_CRD_SRP, NULL);
250 if (cred == NULL) {
251 gnutls_assert();
252 return GNUTLS_E_INSUFICIENT_CRED;
255 username = cred->username;
256 password = cred->password;
258 if (username == NULL || password == NULL)
259 return GNUTLS_E_INSUFICIENT_CRED;
261 /* calc A = g^a % N */
262 if (G == NULL || N == NULL) {
263 gnutls_assert();
264 return GNUTLS_E_INSUFICIENT_CRED;
267 A = _gnutls_calc_srp_A( &_a, G, N);
268 if (A==NULL) {
269 gnutls_assert();
270 return GNUTLS_E_MEMORY_ERROR;
273 if (_gnutls_mpi_print( NULL, &n_a, A)!=0)
274 return GNUTLS_E_MPI_PRINT_FAILED;
276 (*data) = gnutls_malloc(n_a + 2);
277 if ( (*data) == NULL) {
278 gnutls_assert();
279 return GNUTLS_E_MEMORY_ERROR;
282 /* copy A */
283 data_a = (*data);
284 if (_gnutls_mpi_print( &data_a[2], &n_a, A)!=0) {
285 gnutls_free( *data);
286 return GNUTLS_E_MPI_PRINT_FAILED;
289 _gnutls_write_uint16( n_a, data_a);
291 return n_a + 2;
294 /* receive the first key exchange message ( g, n, s) */
295 int proc_srp_server_hello(GNUTLS_STATE state, const opaque * data, int data_size)
297 uint16 n_s, n_g, n_n;
298 size_t _n_s, _n_g, _n_n;
299 const uint8 *data_n;
300 const uint8 *data_g;
301 const uint8 *data_s;
302 uint8 pwd_algo;
303 int i, ret;
304 opaque hd[SRP_MAX_HASH_SIZE];
305 char *username;
306 char *password;
307 const GNUTLS_SRP_CLIENT_CREDENTIALS cred =
308 _gnutls_get_cred(state->gnutls_key, GNUTLS_CRD_SRP, NULL);
310 if (cred == NULL) {
311 gnutls_assert();
312 return GNUTLS_E_INSUFICIENT_CRED;
315 username = cred->username;
316 password = cred->password;
318 if (username == NULL || password == NULL)
319 return GNUTLS_E_INSUFICIENT_CRED;
321 /* read the algorithm used to generate V */
323 i = 0;
324 DECR_LEN( data_size, 1);
325 pwd_algo = data[0];
326 i++;
328 DECR_LEN( data_size, 2);
329 n_g = _gnutls_read_uint16( &data[i]);
330 i += 2;
332 DECR_LEN( data_size, n_g);
333 data_g = &data[i];
334 i += n_g;
335 if (i > data_size) {
336 gnutls_assert();
337 return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
340 DECR_LEN( data_size, 2);
341 n_n = _gnutls_read_uint16( &data[i]);
342 i += 2;
344 DECR_LEN( data_size, n_n);
345 data_n = &data[i];
346 i += n_n;
348 DECR_LEN( data_size, 2);
349 n_s = _gnutls_read_uint16( &data[i]);
350 i += 2;
352 DECR_LEN( data_size, n_s);
353 data_s = &data[i];
354 i += n_s;
356 _n_s = n_s;
357 _n_g = n_g;
358 _n_n = n_n;
360 if (_gnutls_mpi_scan(&N, data_n, &_n_n) != 0 || N == NULL) {
361 gnutls_assert();
362 return GNUTLS_E_MPI_SCAN_FAILED;
365 if (_gnutls_mpi_scan(&G, data_g, &_n_g) != 0 || G == NULL) {
366 gnutls_assert();
367 return GNUTLS_E_MPI_SCAN_FAILED;
370 /* generate x = SHA(s | SHA(U | ":" | p))
371 * (or the equivalent using bcrypt)
373 if ( ( ret =_gnutls_calc_srp_x( username, password, (opaque*)data_s, n_s, pwd_algo, &_n_g, hd)) < 0) {
374 gnutls_assert();
375 return ret;
378 if (_gnutls_mpi_scan(&state->gnutls_key->x, hd, &_n_g) != 0 || state->gnutls_key->x==NULL) {
379 gnutls_assert();
380 return GNUTLS_E_MPI_SCAN_FAILED;
383 return 0;
386 /* just read A and put it to state */
387 int proc_srp_client_kx0(GNUTLS_STATE state, opaque * data, int data_size)
389 size_t _n_A;
391 DECR_LEN( data_size, 2);
392 _n_A = _gnutls_read_uint16( &data[0]);
394 DECR_LEN( data_size, _n_A);
395 if (_gnutls_mpi_scan(&A, &data[2], &_n_A) || A == NULL) {
396 gnutls_assert();
397 return GNUTLS_E_MPI_SCAN_FAILED;
400 return 0;
404 int proc_srp_server_kx2(GNUTLS_STATE state, opaque * data, int data_size)
406 size_t _n_B;
407 int ret;
409 DECR_LEN( data_size, 2);
410 _n_B = _gnutls_read_uint16( &data[0]);
412 DECR_LEN( data_size, _n_B);
413 if (_gnutls_mpi_scan(&B, &data[2], &_n_B) || B==NULL) {
414 gnutls_assert();
415 return GNUTLS_E_MPI_SCAN_FAILED;
418 /* calculate u */
419 state->gnutls_key->u = _gnutls_calc_srp_u( B);
420 if ( state->gnutls_key->u == NULL) {
421 gnutls_assert();
422 return GNUTLS_E_MEMORY_ERROR;
425 /* S = (B - g^x) ^ (a + u * x) % N */
426 S = _gnutls_calc_srp_S2( B, G, state->gnutls_key->x, _a, state->gnutls_key->u, N);
427 if (S==NULL) {
428 gnutls_assert();
429 return GNUTLS_E_MEMORY_ERROR;
433 _gnutls_mpi_release(&A);
434 _gnutls_mpi_release(&_b);
435 _gnutls_mpi_release(&V);
436 _gnutls_mpi_release(&state->gnutls_key->u);
437 _gnutls_mpi_release(&B);
439 ret = _gnutls_generate_key( state->gnutls_key);
440 _gnutls_mpi_release(&S);
442 if (ret < 0)
443 return ret;
445 return 0;
448 #endif /* ENABLE_SRP */