/* 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_kx (gnutls_session_t session, opaque ** data) { int ret; uint8_t *data_n, *data_s; uint8_t *data_g; char *username; SRP_PWD_ENTRY *pwd_entry; srp_server_auth_info_t info; ssize_t data_size; size_t n_b, tmp_size; char buf[64]; uint8_t *data_b; if ((ret = _gnutls_auth_info_set (session, GNUTLS_CRD_SRP, sizeof (srp_server_auth_info_st), 1)) < 0) { gnutls_assert (); return ret; } info = _gnutls_get_auth_info (session); username = info->username; _gnutls_str_cpy (username, MAX_SRP_USERNAME, session->security_parameters.extensions.srp_username); ret = _gnutls_srp_pwd_read_entry (session, username, &pwd_entry); if (ret < 0) { gnutls_assert (); return ret; } /* copy from pwd_entry to local variables (actually in session) */ tmp_size = pwd_entry->g.size; if (_gnutls_mpi_scan_nz (&G, pwd_entry->g.data, &tmp_size) < 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } tmp_size = pwd_entry->n.size; if (_gnutls_mpi_scan_nz (&N, pwd_entry->n.data, &tmp_size) < 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } tmp_size = pwd_entry->v.size; if (_gnutls_mpi_scan_nz (&V, pwd_entry->v.data, &tmp_size) < 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } /* Calculate: B = (k*v + g^b) % N */ B = _gnutls_calc_srp_B (&_b, G, N, V); if (B == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } if (_gnutls_mpi_print (NULL, &n_b, B) != 0) { gnutls_assert (); return GNUTLS_E_MPI_PRINT_FAILED; } /* 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 N (mod n) */ data_n = *data; _gnutls_write_datum16 (data_n, pwd_entry->n); /* copy G (generator) to data */ data_g = &data_n[2 + pwd_entry->n.size]; _gnutls_write_datum16 (data_g, pwd_entry->g); /* copy the salt */ data_s = &data_g[2 + pwd_entry->g.size]; _gnutls_write_datum8 (data_s, pwd_entry->salt); /* Copy the B value */ data_b = &data_s[1 + pwd_entry->salt.size]; if (_gnutls_mpi_print (&data_b[2], &n_b, B) != 0) { gnutls_assert(); return GNUTLS_E_MPI_PRINT_FAILED; } _gnutls_write_uint16 (n_b, data_b); _gnutls_hard_log ("INT: SRP B[%d]: %s\n", n_b, _gnutls_bin2hex (&data_b[2], n_b, buf, sizeof (buf))); _gnutls_srp_entry_free (pwd_entry); return data_size; }
/* 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_kx(gnutls_session_t session, gnutls_buffer_st * data) { int ret; char *username; SRP_PWD_ENTRY *pwd_entry; srp_server_auth_info_t info; size_t tmp_size; extension_priv_data_t epriv; srp_ext_st *priv; ret = _gnutls_ext_get_session_data(session, GNUTLS_EXTENSION_SRP, &epriv); if (ret < 0) { /* peer didn't send a username */ gnutls_assert(); return GNUTLS_E_UNKNOWN_SRP_USERNAME; } priv = epriv; if ((ret = _gnutls_auth_info_set(session, GNUTLS_CRD_SRP, sizeof(srp_server_auth_info_st), 1)) < 0) { gnutls_assert(); return ret; } info = _gnutls_get_auth_info(session, GNUTLS_CRD_SRP); if (info == NULL) return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); username = info->username; _gnutls_str_cpy(username, MAX_USERNAME_SIZE, priv->username); ret = _gnutls_srp_pwd_read_entry(session, username, &pwd_entry); if (ret < 0) { gnutls_assert(); return ret; } /* copy from pwd_entry to local variables (actually in session) */ tmp_size = pwd_entry->g.size; if (_gnutls_mpi_init_scan_nz(&G, pwd_entry->g.data, tmp_size) < 0) { gnutls_assert(); ret = GNUTLS_E_MPI_SCAN_FAILED; goto cleanup; } tmp_size = pwd_entry->n.size; if (_gnutls_mpi_init_scan_nz(&N, pwd_entry->n.data, tmp_size) < 0) { gnutls_assert(); ret = GNUTLS_E_MPI_SCAN_FAILED; goto cleanup; } tmp_size = pwd_entry->v.size; if (_gnutls_mpi_init_scan_nz(&V, pwd_entry->v.data, tmp_size) < 0) { gnutls_assert(); ret = GNUTLS_E_MPI_SCAN_FAILED; goto cleanup; } /* Calculate: B = (k*v + g^b) % N */ B = _gnutls_calc_srp_B(&_b, G, N, V); if (B == NULL) { gnutls_assert(); ret = GNUTLS_E_MEMORY_ERROR; goto cleanup; } /* copy N (mod n) */ ret = _gnutls_buffer_append_data_prefix(data, 16, pwd_entry->n.data, pwd_entry->n.size); if (ret < 0) { gnutls_assert(); goto cleanup; } /* copy G (generator) to data */ ret = _gnutls_buffer_append_data_prefix(data, 16, pwd_entry->g.data, pwd_entry->g.size); if (ret < 0) { gnutls_assert(); goto cleanup; } /* copy the salt */ ret = _gnutls_buffer_append_data_prefix(data, 8, pwd_entry->salt.data, pwd_entry->salt.size); if (ret < 0) { gnutls_assert(); goto cleanup; } /* Copy the B value */ ret = _gnutls_buffer_append_mpi(data, 16, B, 0); if (ret < 0) { gnutls_assert(); goto cleanup; } _gnutls_mpi_log("SRP B: ", B); ret = data->length; cleanup: _gnutls_srp_entry_free(pwd_entry); return ret; }