/* Check if N is a prime and G a generator of the * group. This is check only done if N is big enough. * Otherwise only the included parameters must be used. */ static int group_check_g_n (mpi_t g, mpi_t n) { mpi_t q = NULL, two = NULL, w = NULL; int ret; if (_gnutls_mpi_get_nbits (n) < 2048) { gnutls_assert (); return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; } /* N must be of the form N=2q+1 * where q is also a prime. */ if (_gnutls_prime_check (n, 0) != 0) { _gnutls_dump_mpi ("no prime N: ", n); gnutls_assert (); return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; } two = _gnutls_mpi_new (4); if (two == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } q = _gnutls_mpi_alloc_like (n); if (q == NULL) { gnutls_assert (); ret = GNUTLS_E_MEMORY_ERROR; goto error; } /* q = n-1 */ _gnutls_mpi_sub_ui (q, n, 1); /* q = q/2, remember that q is divisible by 2 (prime - 1) */ _gnutls_mpi_set_ui (two, 2); _gnutls_mpi_div (q, NULL, q, two, 0); if (_gnutls_prime_check (q, 0) != 0) { /* N was not on the form N=2q+1, where q = prime */ _gnutls_dump_mpi ("no prime Q: ", q); gnutls_assert (); return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; } /* We also check whether g is a generator, */ /* check if g < q < N */ if (_gnutls_mpi_cmp (g, q) >= 0) { gnutls_assert (); ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; goto error; } w = _gnutls_mpi_alloc_like (q); if (w == NULL) { gnutls_assert (); ret = GNUTLS_E_MEMORY_ERROR; goto error; } /* check if g^q mod N == N-1 * w = g^q mod N */ _gnutls_mpi_powm (w, g, q, n); /* w++ */ _gnutls_mpi_add_ui (w, w, 1); if (_gnutls_mpi_cmp (w, n) != 0) { gnutls_assert (); ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; goto error; } ret = 0; error: _gnutls_mpi_release (&q); _gnutls_mpi_release (&two); _gnutls_mpi_release (&w); return ret; }
/* just read A and put it to session */ int _gnutls_proc_srp_client_kx (gnutls_session_t session, 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_nz (&A, &data[2], &_n_A) || A == NULL) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } _gnutls_dump_mpi ("SRP A: ", A); _gnutls_dump_mpi ("SRP B: ", B); /* Checks if A % n == 0. */ if ((ret = check_a_mod_n (A, N)) < 0) { gnutls_assert (); return ret; } /* Start the SRP calculations. * - Calculate u */ session->key->u = _gnutls_calc_srp_u (A, B, N); if (session->key->u == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } _gnutls_dump_mpi ("SRP U: ", session->key->u); /* S = (A * v^u) ^ b % N */ S = _gnutls_calc_srp_S1 (A, _b, session->key->u, V, N); if (S == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } _gnutls_dump_mpi ("SRP S: ", S); _gnutls_mpi_release (&A); _gnutls_mpi_release (&_b); _gnutls_mpi_release (&V); _gnutls_mpi_release (&session->key->u); _gnutls_mpi_release (&B); ret = _gnutls_mpi_dprint (&session->key->key, session->key->KEY); _gnutls_mpi_release (&S); if (ret < 0) { gnutls_assert (); return ret; } return 0; }
/* resarr will contain: p(0), q(1), g(2), y(3), x(4). */ int _gnutls_dsa_generate_params (mpi_t * resarr, int *resarr_len, int bits) { int ret; gcry_sexp_t parms, key, list; if (bits < 512 || bits > 1024) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } ret = gcry_sexp_build (&parms, NULL, "(genkey(dsa(nbits %d)))", bits); if (ret != 0) { gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } /* generate the DSA key */ ret = gcry_pk_genkey (&key, parms); gcry_sexp_release (parms); if (ret != 0) { gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } list = gcry_sexp_find_token (key, "p", 0); if (list == NULL) { gnutls_assert (); gcry_sexp_release (key); return GNUTLS_E_INTERNAL_ERROR; } resarr[0] = gcry_sexp_nth_mpi (list, 1, 0); gcry_sexp_release (list); list = gcry_sexp_find_token (key, "q", 0); if (list == NULL) { gnutls_assert (); gcry_sexp_release (key); return GNUTLS_E_INTERNAL_ERROR; } resarr[1] = gcry_sexp_nth_mpi (list, 1, 0); gcry_sexp_release (list); list = gcry_sexp_find_token (key, "g", 0); if (list == NULL) { gnutls_assert (); gcry_sexp_release (key); return GNUTLS_E_INTERNAL_ERROR; } resarr[2] = gcry_sexp_nth_mpi (list, 1, 0); gcry_sexp_release (list); list = gcry_sexp_find_token (key, "y", 0); if (list == NULL) { gnutls_assert (); gcry_sexp_release (key); return GNUTLS_E_INTERNAL_ERROR; } resarr[3] = gcry_sexp_nth_mpi (list, 1, 0); gcry_sexp_release (list); list = gcry_sexp_find_token (key, "x", 0); if (list == NULL) { gnutls_assert (); gcry_sexp_release (key); return GNUTLS_E_INTERNAL_ERROR; } resarr[4] = gcry_sexp_nth_mpi (list, 1, 0); gcry_sexp_release (list); gcry_sexp_release (key); _gnutls_dump_mpi ("p: ", resarr[0]); _gnutls_dump_mpi ("q: ", resarr[1]); _gnutls_dump_mpi ("g: ", resarr[2]); _gnutls_dump_mpi ("y: ", resarr[3]); _gnutls_dump_mpi ("x: ", resarr[4]); *resarr_len = 5; return 0; }
/* return A = g^a % N */ int _gnutls_gen_srp_client_kx (gnutls_session_t session, opaque ** data) { size_t n_a; int ret; uint8_t *data_a; char *username, *password; char buf[64]; 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; } /* calc A = g^a % N */ if (G == NULL || N == NULL) { gnutls_assert (); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } A = _gnutls_calc_srp_A (&_a, G, N); if (A == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } /* Rest of SRP calculations */ /* calculate u */ session->key->u = _gnutls_calc_srp_u (A, B, N); if (session->key->u == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } _gnutls_dump_mpi ("SRP U: ", session->key->u); /* S = (B - g^x) ^ (a + u * x) % N */ S = _gnutls_calc_srp_S2 (B, G, session->key->x, _a, session->key->u, N); if (S == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } _gnutls_dump_mpi ("SRP B: ", B); _gnutls_mpi_release (&_b); _gnutls_mpi_release (&V); _gnutls_mpi_release (&session->key->u); _gnutls_mpi_release (&B); ret = _gnutls_mpi_dprint (&session->key->key, session->key->KEY); _gnutls_mpi_release (&S); if (ret < 0) { gnutls_assert(); return ret; } if (_gnutls_mpi_print (NULL, &n_a, A) != 0) { gnutls_assert (); return GNUTLS_E_MPI_PRINT_FAILED; } (*data) = gnutls_malloc (n_a + 2); if ((*data) == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } /* copy A */ data_a = (*data); if (_gnutls_mpi_print (&data_a[2], &n_a, A) != 0) { gnutls_free (*data); return GNUTLS_E_MPI_PRINT_FAILED; } _gnutls_hard_log ("INT: SRP A[%d]: %s\n", n_a, _gnutls_bin2hex (&data_a[2], n_a, buf, sizeof (buf))); _gnutls_mpi_release (&A); _gnutls_write_uint16 (n_a, data_a); return n_a + 2; }
/* resarr will contain: modulus(0), public exponent(1), private exponent(2), * prime1 - p (3), prime2 - q(4), u (5). */ int _gnutls_rsa_generate_params (mpi_t * resarr, int *resarr_len, int bits) { int ret; gcry_sexp_t parms, key, list; ret = gcry_sexp_build (&parms, NULL, "(genkey(rsa(nbits %d)))", bits); if (ret != 0) { gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } /* generate the RSA key */ ret = gcry_pk_genkey (&key, parms); gcry_sexp_release (parms); if (ret != 0) { gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } list = gcry_sexp_find_token (key, "n", 0); if (list == NULL) { gnutls_assert (); gcry_sexp_release (key); return GNUTLS_E_INTERNAL_ERROR; } resarr[0] = gcry_sexp_nth_mpi (list, 1, 0); gcry_sexp_release (list); list = gcry_sexp_find_token (key, "e", 0); if (list == NULL) { gnutls_assert (); gcry_sexp_release (key); return GNUTLS_E_INTERNAL_ERROR; } resarr[1] = gcry_sexp_nth_mpi (list, 1, 0); gcry_sexp_release (list); list = gcry_sexp_find_token (key, "d", 0); if (list == NULL) { gnutls_assert (); gcry_sexp_release (key); return GNUTLS_E_INTERNAL_ERROR; } resarr[2] = gcry_sexp_nth_mpi (list, 1, 0); gcry_sexp_release (list); list = gcry_sexp_find_token (key, "p", 0); if (list == NULL) { gnutls_assert (); gcry_sexp_release (key); return GNUTLS_E_INTERNAL_ERROR; } resarr[3] = gcry_sexp_nth_mpi (list, 1, 0); gcry_sexp_release (list); list = gcry_sexp_find_token (key, "q", 0); if (list == NULL) { gnutls_assert (); gcry_sexp_release (key); return GNUTLS_E_INTERNAL_ERROR; } resarr[4] = gcry_sexp_nth_mpi (list, 1, 0); gcry_sexp_release (list); list = gcry_sexp_find_token (key, "u", 0); if (list == NULL) { gnutls_assert (); gcry_sexp_release (key); return GNUTLS_E_INTERNAL_ERROR; } resarr[5] = gcry_sexp_nth_mpi (list, 1, 0); gcry_sexp_release (list); gcry_sexp_release (key); _gnutls_dump_mpi ("n: ", resarr[0]); _gnutls_dump_mpi ("e: ", resarr[1]); _gnutls_dump_mpi ("d: ", resarr[2]); _gnutls_dump_mpi ("p: ", resarr[3]); _gnutls_dump_mpi ("q: ", resarr[4]); _gnutls_dump_mpi ("u: ", resarr[5]); *resarr_len = 6; return 0; }