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"
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"
31 #include "gnutls_num.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
= {
53 NULL
, /* certificate */
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
)
79 uint8
*data_n
, *data_s
;
80 uint8
*data_g
, *username
;
82 GNUTLS_SRP_PWD_ENTRY
*pwd_entry
;
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) {
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
) {
100 /* in order to avoid informing the peer that
101 * username does not exist.
103 pwd_entry
= _gnutls_randomize_pwd_entry();
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) {
112 return GNUTLS_E_MPI_PRINT_FAILED
;
114 if (_gnutls_mpi_print( NULL
, &n_n
, pwd_entry
->n
)!=0) {
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
) {
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) {
135 return GNUTLS_E_INVALID_REQUEST
;
140 /* firstly copy the algorithm used to generate the verifier
142 data_g
[0] = pwd_algo
;
144 /* copy G (generator) to data */
148 if(_gnutls_mpi_print( &data_g
[2], &n_g
, G
)!=0) {
150 return GNUTLS_E_MPI_PRINT_FAILED
;
153 _gnutls_write_uint16( n_g
, data_g
);
156 data_n
= &data_g
[2 + n_g
];
158 if (_gnutls_mpi_print( &data_n
[2], &n_n
, N
)!=0) {
160 return GNUTLS_E_MPI_PRINT_FAILED
;
163 _gnutls_write_uint16( n_n
, data_n
);
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
);
178 /* send the second key exchange message */
179 int gen_srp_server_kx2(GNUTLS_STATE state
, opaque
** data
)
185 /* calculate: B = (v + g^b) % N */
186 B
= _gnutls_calc_srp_B( &_b
, G
, N
, V
);
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
) {
198 return GNUTLS_E_MEMORY_ERROR
;
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
);
209 state
->gnutls_key
->u
= _gnutls_calc_srp_u(B
);
210 if (state
->gnutls_key
->u
==NULL
) {
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
);
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
);
240 /* return A = g^a % N */
241 int gen_srp_client_kx0(GNUTLS_STATE state
, opaque
** data
)
247 const GNUTLS_SRP_CLIENT_CREDENTIALS cred
=
248 _gnutls_get_cred(state
->gnutls_key
, GNUTLS_CRD_SRP
, NULL
);
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
) {
264 return GNUTLS_E_INSUFICIENT_CRED
;
267 A
= _gnutls_calc_srp_A( &_a
, G
, N
);
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
) {
279 return GNUTLS_E_MEMORY_ERROR
;
284 if (_gnutls_mpi_print( &data_a
[2], &n_a
, A
)!=0) {
286 return GNUTLS_E_MPI_PRINT_FAILED
;
289 _gnutls_write_uint16( n_a
, data_a
);
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
;
304 opaque hd
[SRP_MAX_HASH_SIZE
];
307 const GNUTLS_SRP_CLIENT_CREDENTIALS cred
=
308 _gnutls_get_cred(state
->gnutls_key
, GNUTLS_CRD_SRP
, NULL
);
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 */
324 DECR_LEN( data_size
, 1);
328 DECR_LEN( data_size
, 2);
329 n_g
= _gnutls_read_uint16( &data
[i
]);
332 DECR_LEN( data_size
, n_g
);
337 return GNUTLS_E_UNEXPECTED_PACKET_LENGTH
;
340 DECR_LEN( data_size
, 2);
341 n_n
= _gnutls_read_uint16( &data
[i
]);
344 DECR_LEN( data_size
, n_n
);
348 DECR_LEN( data_size
, 2);
349 n_s
= _gnutls_read_uint16( &data
[i
]);
352 DECR_LEN( data_size
, n_s
);
360 if (_gnutls_mpi_scan(&N
, data_n
, &_n_n
) != 0 || N
== NULL
) {
362 return GNUTLS_E_MPI_SCAN_FAILED
;
365 if (_gnutls_mpi_scan(&G
, data_g
, &_n_g
) != 0 || G
== NULL
) {
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) {
378 if (_gnutls_mpi_scan(&state
->gnutls_key
->x
, hd
, &_n_g
) != 0 || state
->gnutls_key
->x
==NULL
) {
380 return GNUTLS_E_MPI_SCAN_FAILED
;
386 /* just read A and put it to state */
387 int proc_srp_client_kx0(GNUTLS_STATE state
, opaque
* data
, int data_size
)
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
) {
397 return GNUTLS_E_MPI_SCAN_FAILED
;
404 int proc_srp_server_kx2(GNUTLS_STATE state
, opaque
* data
, int data_size
)
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
) {
415 return GNUTLS_E_MPI_SCAN_FAILED
;
419 state
->gnutls_key
->u
= _gnutls_calc_srp_u( B
);
420 if ( state
->gnutls_key
->u
== NULL
) {
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
);
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
);
448 #endif /* ENABLE_SRP */