#include <gnutls_str.h>
#include <gnutls_datum.h>
-int _gnutls_gen_srp_server_kx2(gnutls_session, opaque **);
+int _gnutls_gen_srp_server_kx0(gnutls_session, opaque **);
int _gnutls_gen_srp_client_kx0(gnutls_session, opaque **);
-int _gnutls_proc_srp_server_kx2(gnutls_session, opaque *, size_t);
+int _gnutls_proc_srp_server_kx0(gnutls_session, opaque *, size_t);
int _gnutls_proc_srp_client_kx0(gnutls_session, opaque *, size_t);
const MOD_AUTH_STRUCT srp_auth_struct = {
"SRP",
NULL,
NULL,
+ _gnutls_gen_srp_server_kx0,
NULL,
- _gnutls_gen_srp_server_kx2,
_gnutls_gen_srp_client_kx0,
NULL,
NULL,
NULL,
NULL, /* certificate */
+ _gnutls_proc_srp_server_kx0,
NULL,
- _gnutls_proc_srp_server_kx2,
_gnutls_proc_srp_client_kx0,
NULL,
NULL,
/* Send the first key exchange message ( g, n, s) and append the verifier algorithm number
* Data is allocated by the caller, and should have data_size size.
*/
-int _gnutls_gen_srp_server_hello(gnutls_session state, opaque * data, size_t _data_size)
+int _gnutls_gen_srp_server_kx0(gnutls_session state, opaque ** data)
{
int ret;
uint8 *data_n, *data_s;
SRP_PWD_ENTRY *pwd_entry;
int err;
SRP_SERVER_AUTH_INFO info;
- ssize_t data_size = _data_size;
+ ssize_t data_size;
+ size_t n_b;
+ uint8 *data_b;
if ( (ret=_gnutls_auth_info_set( state, GNUTLS_CRD_SRP, sizeof( SRP_SERVER_AUTH_INFO_INT), 1)) < 0) {
gnutls_assert();
return GNUTLS_E_MPI_SCAN_FAILED;
}
- if ((size_t)data_size < pwd_entry->n.size +
- pwd_entry->g.size + pwd_entry->salt.size + 5) {
- gnutls_assert();
- return GNUTLS_E_INVALID_REQUEST;
- }
-
- /* copy the salt
+ /* Calculate: B = (3v + g^b) % N
*/
- data_s = data;
-
- _gnutls_write_datum8( data_s, pwd_entry->salt);
-
- /* copy N (mod n) */
- data_n = &data_s[1 + pwd_entry->salt.size];
- _gnutls_write_datum16( data_n, pwd_entry->n);
-
-
- data_g = &data_n[2 + pwd_entry->n.size];
- /* copy G (generator) to data */
- _gnutls_write_datum16( data_g, pwd_entry->g);
-
-
- ret = pwd_entry->g.size + pwd_entry->n.size +
- pwd_entry->salt.size + 5;
- _gnutls_srp_entry_free( pwd_entry);
-
- return ret;
-}
-
-/* send the second key exchange message */
-int _gnutls_gen_srp_server_kx2(gnutls_session state, opaque ** data)
-{
- int ret;
- size_t n_b;
- uint8 *data_b;
-
- /* calculate: B = (v + g^b) % N */
B = _gnutls_calc_srp_B( &_b, G, N, V);
if (B==NULL) {
gnutls_assert();
return GNUTLS_E_MPI_PRINT_FAILED;
}
- (*data) = gnutls_malloc(n_b + 2);
+
+ /* Allocate size to hold the N, g, s, B
+ */
+
+ data_size = (pwd_entry->n.size + 2 + pwd_entry->g.size + 2 +
+ pwd_entry->salt.size + 1) + (n_b + 2);
+
+ (*data) = gnutls_malloc( data_size);
if ( (*data) == NULL) {
gnutls_assert();
return GNUTLS_E_MEMORY_ERROR;
}
- /* copy B */
- data_b = (*data);
- if (_gnutls_mpi_print( &data_b[2], &n_b, B)!=0)
- return GNUTLS_E_MPI_PRINT_FAILED;
+ /* copy N (mod n)
+ */
+ data_n = *data;
+ _gnutls_write_datum16( data_n, pwd_entry->n);
- _gnutls_write_uint16( n_b, data_b);
- /* calculate u */
- state->key->u = _gnutls_calc_srp_u(B);
- if (state->key->u==NULL) {
- gnutls_assert();
- gnutls_free( *data);
- return GNUTLS_E_MEMORY_ERROR;
- }
+ /* copy G (generator) to data
+ */
+ data_g = &data_n[2 + pwd_entry->n.size];
+ _gnutls_write_datum16( data_g, pwd_entry->g);
- /* S = (A * v^u) ^ b % N */
- S = _gnutls_calc_srp_S1( A, _b, state->key->u, V, N);
- if ( S==NULL) {
- gnutls_assert();
- gnutls_free( *data);
- return GNUTLS_E_MEMORY_ERROR;
- }
- _gnutls_mpi_release(&A);
- _gnutls_mpi_release(&_b);
- _gnutls_mpi_release(&V);
- _gnutls_mpi_release(&state->key->u);
- _gnutls_mpi_release(&B);
+ /* copy the salt
+ */
+ data_s = &data_g[2 + pwd_entry->g.size];
+ _gnutls_write_datum8( data_s, pwd_entry->salt);
- ret = _gnutls_generate_key( state->key);
- _gnutls_mpi_release( &S);
- if (ret < 0) {
- gnutls_assert();
- return ret;
- }
+ /* Copy the B value
+ */
- return n_b + 2;
-}
+ data_b = &data_s[1+pwd_entry->salt.size];
+ if (_gnutls_mpi_print( &data_b[2], &n_b, B)!=0)
+ return GNUTLS_E_MPI_PRINT_FAILED;
+ _gnutls_write_uint16( n_b, data_b);
+ _gnutls_srp_entry_free( pwd_entry);
+
+ return data_size;
+}
/* return A = g^a % N */
int _gnutls_gen_srp_client_kx0(gnutls_session state, opaque ** data)
{
size_t n_a;
+ int ret;
uint8 *data_a;
char *username;
char *password;
return GNUTLS_E_MEMORY_ERROR;
}
+ /* Rest of SRP calculations
+ */
+
+ /* calculate u */
+ state->key->u = _gnutls_calc_srp_u(A, B);
+ if ( state->key->u == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ /* S = (B - g^x) ^ (a + u * x) % N */
+ S = _gnutls_calc_srp_S2( B, G, state->key->x, _a, state->key->u, N);
+ if (S==NULL) {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ _gnutls_mpi_release(&_b);
+ _gnutls_mpi_release(&V);
+ _gnutls_mpi_release(&state->key->u);
+ _gnutls_mpi_release(&B);
+
+ ret = _gnutls_generate_key( state->key);
+ _gnutls_mpi_release(&S);
+
+ if (ret < 0)
+ return ret;
+
if (_gnutls_mpi_print( NULL, &n_a, A)!=0) {
gnutls_assert();
return GNUTLS_E_MPI_PRINT_FAILED;
gnutls_free( *data);
return GNUTLS_E_MPI_PRINT_FAILED;
}
-
+ _gnutls_mpi_release(&A);
+
_gnutls_write_uint16( n_a, data_a);
return n_a + 2;
}
-/* receive the first key exchange message ( g, n, s) */
-int _gnutls_proc_srp_server_hello(gnutls_session state, const opaque * data, size_t _data_size)
+
+/* just read A and put it to state */
+int _gnutls_proc_srp_client_kx0(gnutls_session state, opaque * data, size_t _data_size)
+{
+ size_t _n_A;
+ ssize_t data_size = _data_size;
+ int ret;
+
+ DECR_LEN( data_size, 2);
+ _n_A = _gnutls_read_uint16( &data[0]);
+
+ DECR_LEN( data_size, _n_A);
+ if (_gnutls_mpi_scan(&A, &data[2], &_n_A) || A == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_MPI_SCAN_FAILED;
+ }
+
+ /* Start the SRP calculations.
+ * - Calculate u
+ */
+ state->key->u = _gnutls_calc_srp_u(A, B);
+ if (state->key->u==NULL) {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ /* S = (A * v^u) ^ b % N
+ */
+ S = _gnutls_calc_srp_S1( A, _b, state->key->u, V, N);
+ if ( S==NULL) {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ _gnutls_mpi_release(&A);
+ _gnutls_mpi_release(&_b);
+ _gnutls_mpi_release(&V);
+ _gnutls_mpi_release(&state->key->u);
+ _gnutls_mpi_release(&B);
+
+ ret = _gnutls_generate_key( state->key);
+ _gnutls_mpi_release( &S);
+
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
+ return 0;
+}
+
+/* receive the key exchange message ( n, g, s, B)
+ */
+int _gnutls_proc_srp_server_kx0(gnutls_session state, opaque * data, size_t _data_size)
{
uint8 n_s;
- uint16 n_g, n_n;
- size_t _n_s, _n_g, _n_n;
+ uint16 n_g, n_n, n_b;
+ size_t _n_s, _n_g, _n_n, _n_b;
const uint8 *data_n;
const uint8 *data_g;
const uint8 *data_s;
+ const uint8 *data_b;
int i, ret;
opaque hd[SRP_MAX_HASH_SIZE];
char *username, *password;
i = 0;
- DECR_LEN( data_size, 1);
- n_s = data[i];
- i += 1;
-
- DECR_LEN( data_size, n_s);
- data_s = &data[i];
- i += n_s;
-
+ /* Read N
+ */
DECR_LEN( data_size, 2);
n_n = _gnutls_read_uint16( &data[i]);
i += 2;
DECR_LEN( data_size, n_n);
data_n = &data[i];
i += n_n;
-
+
+ /* Read G
+ */
DECR_LEN( data_size, 2);
n_g = _gnutls_read_uint16( &data[i]);
i += 2;
data_g = &data[i];
i += n_g;
+ /* Read salt
+ */
+ DECR_LEN( data_size, 1);
+ n_s = data[i];
+ i += 1;
+
+ DECR_LEN( data_size, n_s);
+ data_s = &data[i];
+ i += n_s;
+
+ /* Read B
+ */
+ DECR_LEN( data_size, 2);
+ n_b = data[i];
+ i += 2;
+
+ DECR_LEN( data_size, n_b);
+ data_b = &data[i];
+ i += n_b;
+
_n_s = n_s;
_n_g = n_g;
_n_n = n_n;
+ _n_b = n_b;
+
+ if (_gnutls_mpi_scan(&N, data_n, &_n_n) != 0) {
+ gnutls_assert();
+ return GNUTLS_E_MPI_SCAN_FAILED;
+ }
- if (_gnutls_mpi_scan(&N, data_n, &_n_n) != 0 || N == NULL) {
+ if (_gnutls_mpi_scan(&G, data_g, &_n_g) != 0) {
gnutls_assert();
return GNUTLS_E_MPI_SCAN_FAILED;
}
- if (_gnutls_mpi_scan(&G, data_g, &_n_g) != 0 || G == NULL) {
+ if (_gnutls_mpi_scan(&B, data_b, &_n_b) != 0) {
gnutls_assert();
return GNUTLS_E_MPI_SCAN_FAILED;
}
return ret;
}
- if (_gnutls_mpi_scan(&state->key->x, hd, &_n_g) != 0 || state->key->x==NULL) {
+ if (_gnutls_mpi_scan(&state->key->x, hd, &_n_g) != 0) {
gnutls_assert();
return GNUTLS_E_MPI_SCAN_FAILED;
}
-
- return 0;
-}
-
-/* just read A and put it to state */
-int _gnutls_proc_srp_client_kx0(gnutls_session state, opaque * data, size_t _data_size)
-{
- size_t _n_A;
- ssize_t data_size = _data_size;
-
- DECR_LEN( data_size, 2);
- _n_A = _gnutls_read_uint16( &data[0]);
-
- DECR_LEN( data_size, _n_A);
- if (_gnutls_mpi_scan(&A, &data[2], &_n_A) || A == NULL) {
- gnutls_assert();
- return GNUTLS_E_MPI_SCAN_FAILED;
- }
-
- return 0;
-}
-
-
-int _gnutls_proc_srp_server_kx2(gnutls_session state, opaque * data, size_t _data_size)
-{
- size_t _n_B;
- ssize_t data_size = _data_size;
- int ret;
-
- DECR_LEN( data_size, 2);
- _n_B = _gnutls_read_uint16( &data[0]);
-
- DECR_LEN( data_size, _n_B);
- if (_gnutls_mpi_scan(&B, &data[2], &_n_B) || B==NULL) {
- gnutls_assert();
- return GNUTLS_E_MPI_SCAN_FAILED;
- }
-
- /* calculate u */
- state->key->u = _gnutls_calc_srp_u( B);
- if ( state->key->u == NULL) {
- gnutls_assert();
- return GNUTLS_E_MEMORY_ERROR;
- }
-
- /* S = (B - g^x) ^ (a + u * x) % N */
- S = _gnutls_calc_srp_S2( B, G, state->key->x, _a, state->key->u, N);
- if (S==NULL) {
- gnutls_assert();
- return GNUTLS_E_MEMORY_ERROR;
- }
- _gnutls_mpi_release(&A);
- _gnutls_mpi_release(&_b);
- _gnutls_mpi_release(&V);
- _gnutls_mpi_release(&state->key->u);
- _gnutls_mpi_release(&B);
-
- ret = _gnutls_generate_key( state->key);
- _gnutls_mpi_release(&S);
-
- if (ret < 0)
- return ret;
-
- return _data_size - data_size; /* return the remaining data
- * needed in auth_srp_rsa.
- */
+ return 0;
}
#endif /* ENABLE_SRP */
#include <gnutls_x509.h>
#include <gnutls_extra.h>
-static int gen_srp_cert_server_kx2(gnutls_session, opaque **);
-static int proc_srp_cert_server_kx2(gnutls_session, opaque *, size_t);
+static int gen_srp_cert_server_kx0(gnutls_session, opaque **);
+static int proc_srp_cert_server_kx0(gnutls_session, opaque *, size_t);
const MOD_AUTH_STRUCT srp_rsa_auth_struct = {
"SRP",
_gnutls_gen_cert_server_certificate,
NULL,
+ gen_srp_cert_server_kx0,
NULL,
- gen_srp_cert_server_kx2,
_gnutls_gen_srp_client_kx0,
NULL,
NULL,
_gnutls_proc_cert_server_certificate,
NULL, /* certificate */
+ proc_srp_cert_server_kx0,
NULL,
- proc_srp_cert_server_kx2,
_gnutls_proc_srp_client_kx0,
NULL,
NULL,
"SRP",
_gnutls_gen_cert_server_certificate,
NULL,
+ gen_srp_cert_server_kx0,
NULL,
- gen_srp_cert_server_kx2,
_gnutls_gen_srp_client_kx0,
NULL,
NULL,
_gnutls_proc_cert_server_certificate,
NULL, /* certificate */
+ proc_srp_cert_server_kx0,
NULL,
- proc_srp_cert_server_kx2,
_gnutls_proc_srp_client_kx0,
NULL,
NULL,
NULL
};
-static int gen_srp_cert_server_kx2(gnutls_session session, opaque ** data)
+static int gen_srp_cert_server_kx0(gnutls_session session, opaque ** data)
{
ssize_t ret, data_size;
gnutls_datum signature, ddata;
gnutls_private_key *apr_pkey;
int apr_cert_list_length;
- ret = _gnutls_gen_srp_server_kx2( session, data);
+ ret = _gnutls_gen_srp_server_kx0( session, data);
if (ret < 0) return ret;
extern OPENPGP_CERT2GNUTLS_CERT _E_gnutls_openpgp_cert2gnutls_cert;
-static int proc_srp_cert_server_kx2(gnutls_session session, opaque * data, size_t _data_size)
+static int proc_srp_cert_server_kx0(gnutls_session session, opaque * data, size_t _data_size)
{
ssize_t ret;
int sigsize;
gnutls_cert peer_cert;
opaque* p;
- ret = _gnutls_proc_srp_server_kx2( session, data, _data_size);
+ ret = _gnutls_proc_srp_server_kx0( session, data, _data_size);
if (ret < 0) return ret;
data_size = _data_size - ret;
*/
GNUTLS_MPI _gnutls_calc_srp_B(GNUTLS_MPI * ret_b, GNUTLS_MPI g, GNUTLS_MPI n, GNUTLS_MPI v)
{
- GNUTLS_MPI tmpB;
+ GNUTLS_MPI tmpB, tmpV;
GNUTLS_MPI b, B;
int bits;
- /* calculate: B = (v + g^b) % N */
+ /* calculate: B = (3v + g^b) % N
+ */
bits = _gnutls_mpi_get_nbits(n);
b = _gnutls_mpi_new(bits); /* FIXME: allocate in secure memory */
if (b==NULL) {
gnutls_assert();
return NULL;
}
+
+ tmpV = _gnutls_mpi_alloc_like(n);
+
+ if (tmpV == NULL) {
+ _gnutls_mpi_release(&b);
+ return NULL;
+ }
_gnutls_mpi_randomize(b, bits, GCRY_STRONG_RANDOM);
if (tmpB==NULL) {
gnutls_assert();
_gnutls_mpi_release( &b);
+ _gnutls_mpi_release(&tmpV);
return NULL;
}
gnutls_assert();
_gnutls_mpi_release( &b);
_gnutls_mpi_release( &tmpB);
+ _gnutls_mpi_release(&tmpV);
return NULL;
}
+ _gnutls_mpi_mul_ui(tmpV, v, 3);
+
_gnutls_mpi_powm(tmpB, g, b, n);
- _gnutls_mpi_addm(B, v, tmpB, n);
+ _gnutls_mpi_addm(B, tmpV, tmpB, n);
_gnutls_mpi_release(&tmpB);
+ _gnutls_mpi_release(&tmpV);
if (ret_b)
*ret_b = b;
return B;
}
-GNUTLS_MPI _gnutls_calc_srp_u(GNUTLS_MPI B)
+GNUTLS_MPI _gnutls_calc_srp_u(GNUTLS_MPI A, GNUTLS_MPI B)
{
- size_t b_size;
- opaque *b_holder, hd[MAX_HASH_SIZE];
+ size_t b_size, a_size;
+ opaque *holder, hd[MAX_HASH_SIZE];
+ size_t holder_size;
GNUTLS_HASH_HANDLE td;
uint32 u;
- GNUTLS_MPI ret;
+ int ret;
+ GNUTLS_MPI res;
+ _gnutls_mpi_print( NULL, &a_size, A);
_gnutls_mpi_print( NULL, &b_size, B);
- b_holder = gnutls_malloc(b_size);
- if (b_holder==NULL) return NULL;
- _gnutls_mpi_print( b_holder, &b_size, B);
+ holder_size = a_size + b_size;
+ holder = gnutls_alloca(holder_size);
+ if (holder==NULL) return NULL;
+
+ _gnutls_mpi_print( holder, &a_size, A);
+ _gnutls_mpi_print( &holder[a_size], &b_size, B);
td = _gnutls_hash_init(GNUTLS_MAC_SHA);
if (td==NULL) {
- gnutls_free(b_holder);
+ gnutls_afree(holder);
gnutls_assert();
return NULL;
}
- _gnutls_hash(td, b_holder, b_size);
+ _gnutls_hash(td, holder, holder_size);
_gnutls_hash_deinit(td, hd);
/* convert the first 4 bytes of hd to uint32
*/
- u = _gnutls_read_uint32( hd);
+ ret = _gnutls_mpi_scan( &res, holder, &holder_size);
+ gnutls_afree(holder);
- gnutls_free(b_holder);
-
- ret = _gnutls_mpi_set_ui(NULL, u);
- if (ret==NULL) {
+ if (ret < 0) {
gnutls_assert();
return NULL;
}
- return ret;
+ return res;
}
/* S = (A * v^u) ^ b % N
*/
GNUTLS_MPI _gnutls_calc_srp_S1(GNUTLS_MPI A, GNUTLS_MPI b, GNUTLS_MPI u, GNUTLS_MPI v, GNUTLS_MPI n)
{
- GNUTLS_MPI tmp1, tmp2;
- GNUTLS_MPI S;
+ GNUTLS_MPI tmp1=NULL, tmp2 = NULL;
+ GNUTLS_MPI S = NULL;
S = _gnutls_mpi_alloc_like(n);
if (S==NULL)
tmp1 = _gnutls_mpi_alloc_like(n);
tmp2 = _gnutls_mpi_alloc_like(n);
- if (tmp1 == NULL || tmp2 == NULL) {
- _gnutls_mpi_release(&tmp1);
- _gnutls_mpi_release(&tmp2);
- return NULL;
- }
+ if (tmp1 == NULL || tmp2 == NULL)
+ goto freeall;
_gnutls_mpi_powm(tmp1, v, u, n);
_gnutls_mpi_mulm(tmp2, A, tmp1, n);
- _gnutls_mpi_release(&tmp1);
-
_gnutls_mpi_powm(S, tmp2, b, n);
- _gnutls_mpi_release(&tmp2);
return S;
+
+ freeall:
+ _gnutls_mpi_release(&tmp1);
+ _gnutls_mpi_release(&tmp2);
+
+ return NULL;
}
/* A = g^a % N
}
-/* S = (B - g^x) ^ (a + u * x) % N
+/* S = (B - 3*g^x) ^ (a + u * x) % N
* this is our shared key
*/
GNUTLS_MPI _gnutls_calc_srp_S2(GNUTLS_MPI B, GNUTLS_MPI g, GNUTLS_MPI x, GNUTLS_MPI a, GNUTLS_MPI u, GNUTLS_MPI n)
{
- GNUTLS_MPI S, tmp1, tmp2, tmp4;
+ GNUTLS_MPI S=NULL, tmp1=NULL, tmp2=NULL;
+ GNUTLS_MPI tmp4=NULL, tmp3=NULL;
S = _gnutls_mpi_alloc_like(n);
if (S==NULL)
tmp1 = _gnutls_mpi_alloc_like(n);
tmp2 = _gnutls_mpi_alloc_like(n);
- if (tmp1 == NULL || tmp2 == NULL) {
- _gnutls_mpi_release(&tmp1);
- _gnutls_mpi_release(&tmp2);
- return NULL;
+ tmp3 = _gnutls_mpi_alloc_like(n);
+ if (tmp1 == NULL || tmp2 == NULL || tmp3 == NULL) {
+ goto freeall;
}
- _gnutls_mpi_powm(tmp1, g, x, n);
-
- _gnutls_mpi_subm(tmp2, B, tmp1, n);
+ _gnutls_mpi_powm(tmp1, g, x, n); /* g^x */
+ _gnutls_mpi_mul_ui(tmp3, tmp1, 3); /* 3*g^x */
+ _gnutls_mpi_subm(tmp2, B, tmp3, n);
tmp4 = _gnutls_mpi_alloc_like(n);
if (tmp4==NULL)
- return NULL;
+ goto freeall;
_gnutls_mpi_mul(tmp1, u, x);
_gnutls_mpi_add(tmp4, a, tmp1);
- _gnutls_mpi_release(&tmp1);
-
_gnutls_mpi_powm(S, tmp2, tmp4, n);
+
+ return S;
+
+ freeall:
+
+ _gnutls_mpi_release(&tmp1);
_gnutls_mpi_release(&tmp2);
+ _gnutls_mpi_release(&tmp3);
_gnutls_mpi_release(&tmp4);
+ _gnutls_mpi_release(&S);
- return S;
+ return NULL;
}
/**