/* receive the key exchange message ( n, g, s, B) */ int _gnutls_proc_srp_server_kx (gnutls_session_t session, opaque * data, size_t _data_size) { uint8_t n_s; uint16_t n_g, n_n, n_b; size_t _n_s, _n_g, _n_n, _n_b; const uint8_t *data_n; const uint8_t *data_g; const uint8_t *data_s; const uint8_t *data_b; int i, ret; opaque hd[SRP_MAX_HASH_SIZE]; char *username, *password; ssize_t data_size = _data_size; gnutls_srp_client_credentials_t cred; cred = (gnutls_srp_client_credentials_t) _gnutls_get_cred (session->key, GNUTLS_CRD_SRP, NULL); if (cred == NULL) { gnutls_assert (); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } if (session->internals.srp_username == NULL) { username = cred->username; password = cred->password; } else { username = session->internals.srp_username; password = session->internals.srp_password; } if (username == NULL || password == NULL) { gnutls_assert (); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } i = 0; /* 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; DECR_LEN (data_size, n_g); 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 = _gnutls_read_uint16 (&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_nz (&N, data_n, &_n_n) != 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } if (_gnutls_mpi_scan_nz (&G, data_g, &_n_g) != 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } if (_gnutls_mpi_scan_nz (&B, data_b, &_n_b) != 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } /* Check if the g and n are from the SRP * draft. Otherwise check if N is a prime and G * a generator. */ if ((ret = check_g_n (data_g, _n_g, data_n, _n_n)) < 0) { _gnutls_x509_log ("Checking the SRP group parameters.\n"); if ((ret = group_check_g_n (G, N)) < 0) { gnutls_assert (); return ret; } } /* Checks if b % n == 0 */ if ((ret = check_b_mod_n (B, N)) < 0) { gnutls_assert (); return ret; } /* generate x = SHA(s | SHA(U | ":" | p)) * (or the equivalent using bcrypt) */ if ((ret = _gnutls_calc_srp_x (username, password, (opaque *) data_s, n_s, &_n_g, hd)) < 0) { gnutls_assert (); return ret; } if (_gnutls_mpi_scan_nz (&session->key->x, hd, &_n_g) != 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } return i; /* return the processed data * needed in auth_srp_rsa. */ }
/* receive the key exchange message ( n, g, s, B) */ int _gnutls_proc_srp_server_kx(gnutls_session_t session, uint8_t * data, size_t _data_size) { uint8_t n_s; uint16_t n_g, n_n, n_b; size_t _n_g, _n_n, _n_b; const uint8_t *data_n; const uint8_t *data_g; const uint8_t *data_s; const uint8_t *data_b; int i, ret; uint8_t hd[SRP_MAX_HASH_SIZE]; char *username, *password; ssize_t data_size = _data_size; gnutls_srp_client_credentials_t cred; extension_priv_data_t epriv; srp_ext_st *priv; ret = _gnutls_ext_get_session_data(session, GNUTLS_EXTENSION_SRP, &epriv); if (ret < 0) { gnutls_assert(); return GNUTLS_E_UNKNOWN_SRP_USERNAME; } priv = epriv; cred = (gnutls_srp_client_credentials_t) _gnutls_get_cred(session, GNUTLS_CRD_SRP); if (cred == NULL) { gnutls_assert(); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } if (priv->username == NULL) { username = cred->username; password = cred->password; } else { username = priv->username; password = priv->password; } if (username == NULL || password == NULL) { gnutls_assert(); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } i = 0; /* 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; DECR_LEN(data_size, n_g); 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 = _gnutls_read_uint16(&data[i]); i += 2; DECR_LEN(data_size, n_b); data_b = &data[i]; i += n_b; _n_g = n_g; _n_n = n_n; _n_b = n_b; if (_gnutls_mpi_init_scan_nz(&N, data_n, _n_n) != 0) { gnutls_assert(); return GNUTLS_E_MPI_SCAN_FAILED; } if (_gnutls_mpi_init_scan_nz(&G, data_g, _n_g) != 0) { gnutls_assert(); return GNUTLS_E_MPI_SCAN_FAILED; } if (_gnutls_mpi_init_scan_nz(&B, data_b, _n_b) != 0) { gnutls_assert(); return GNUTLS_E_MPI_SCAN_FAILED; } /* Check if the g and n are from the SRP * draft. Otherwise check if N is a prime and G * a generator. */ if ((ret = check_g_n(data_g, _n_g, data_n, _n_n)) < 0) { _gnutls_audit_log(session, "SRP group parameters are not in the white list. Checking validity.\n"); if ((ret = group_check_g_n(session, G, N)) < 0) { gnutls_assert(); return ret; } } /* Checks if b % n == 0 */ if ((ret = check_param_mod_n(B, N, 0)) < 0) { gnutls_assert(); return ret; } /* generate x = SHA(s | SHA(U | ":" | p)) * (or the equivalent using bcrypt) */ if ((ret = _gnutls_calc_srp_x(username, password, (uint8_t *) data_s, n_s, &_n_g, hd)) < 0) { gnutls_assert(); return ret; } if (_gnutls_mpi_init_scan_nz(&session->key.x, hd, _n_g) != 0) { gnutls_assert(); return GNUTLS_E_MPI_SCAN_FAILED; } return i; /* return the processed data * needed in auth_srp_rsa. */ }