/** * gnutls_deinit: * @session: is a #gnutls_session_t structure. * * This function clears all buffers associated with the @session. * This function will also remove session data from the session * database if the session was terminated abnormally. **/ void gnutls_deinit(gnutls_session_t session) { unsigned int i; if (session == NULL) return; _gnutls_rnd_refresh(); /* remove auth info firstly */ _gnutls_free_auth_info(session); _gnutls_handshake_internal_state_clear(session); _gnutls_handshake_io_buffer_clear(session); _gnutls_ext_free_session_data(session); for (i = 0; i < MAX_EPOCH_INDEX; i++) if (session->record_parameters[i] != NULL) { _gnutls_epoch_free(session, session->record_parameters[i]); session->record_parameters[i] = NULL; } _gnutls_buffer_clear(&session->internals.handshake_hash_buffer); _gnutls_buffer_clear(&session->internals.hb_remote_data); _gnutls_buffer_clear(&session->internals.hb_local_data); _gnutls_buffer_clear(&session->internals.record_presend_buffer); _mbuffer_head_clear(&session->internals.record_buffer); _mbuffer_head_clear(&session->internals.record_recv_buffer); _mbuffer_head_clear(&session->internals.record_send_buffer); gnutls_credentials_clear(session); _gnutls_selected_certs_deinit(session); gnutls_pk_params_release(&session->key.ecdh_params); gnutls_pk_params_release(&session->key.dh_params); zrelease_temp_mpi_key(&session->key.ecdh_x); zrelease_temp_mpi_key(&session->key.ecdh_y); zrelease_temp_mpi_key(&session->key.client_Y); zrelease_temp_mpi_key(&session->key.srp_p); zrelease_temp_mpi_key(&session->key.srp_g); zrelease_temp_mpi_key(&session->key.srp_key); zrelease_temp_mpi_key(&session->key.u); zrelease_temp_mpi_key(&session->key.a); zrelease_temp_mpi_key(&session->key.x); zrelease_temp_mpi_key(&session->key.A); zrelease_temp_mpi_key(&session->key.B); zrelease_temp_mpi_key(&session->key.b); /* RSA */ zrelease_temp_mpi_key(&session->key.rsa[0]); zrelease_temp_mpi_key(&session->key.rsa[1]); _gnutls_free_temp_key_datum(&session->key.key); gnutls_free(session); }
/* just read A and put it to session */ int _gnutls_proc_srp_client_kx(gnutls_session_t session, uint8_t * data, size_t _data_size) { ssize_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_init_scan_nz(&A, &data[2], _n_A) || A == NULL) { gnutls_assert(); return GNUTLS_E_MPI_SCAN_FAILED; } _gnutls_mpi_log("SRP A: ", A); _gnutls_mpi_log("SRP B: ", B); /* Checks if A % n == 0. */ if ((ret = check_param_mod_n(A, N, 1)) < 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_mpi_log("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_mpi_log("SRP S: ", S); _gnutls_mpi_release(&A); zrelease_temp_mpi_key(&_b); zrelease_temp_mpi_key(&V); zrelease_temp_mpi_key(&session->key.u); zrelease_temp_mpi_key(&B); ret = _gnutls_mpi_dprint(session->key.srp_key, &session->key.key); zrelease_temp_mpi_key(&S); if (ret < 0) { gnutls_assert(); return ret; } return 0; }
static void deinit_keys(gnutls_session_t session) { gnutls_pk_params_release(&session->key.ecdh_params); gnutls_pk_params_release(&session->key.dh_params); zrelease_temp_mpi_key(&session->key.ecdh_x); zrelease_temp_mpi_key(&session->key.ecdh_y); _gnutls_free_temp_key_datum(&session->key.ecdhx); zrelease_temp_mpi_key(&session->key.client_Y); /* SRP */ zrelease_temp_mpi_key(&session->key.srp_p); zrelease_temp_mpi_key(&session->key.srp_g); zrelease_temp_mpi_key(&session->key.srp_key); zrelease_temp_mpi_key(&session->key.u); zrelease_temp_mpi_key(&session->key.a); zrelease_temp_mpi_key(&session->key.x); zrelease_temp_mpi_key(&session->key.A); zrelease_temp_mpi_key(&session->key.B); zrelease_temp_mpi_key(&session->key.b); _gnutls_free_temp_key_datum(&session->key.key); _gnutls_free_temp_key_datum(&session->key.key); }
/* return A = g^a % N */ int _gnutls_gen_srp_client_kx(gnutls_session_t session, gnutls_buffer_st * data) { int ret; char *username, *password; 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) { /* peer didn't send a username */ 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; } /* 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_mpi_log("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_mpi_log("SRP B: ", B); zrelease_temp_mpi_key(&_b); zrelease_temp_mpi_key(&V); zrelease_temp_mpi_key(&session->key.u); zrelease_temp_mpi_key(&B); ret = _gnutls_mpi_dprint(session->key.srp_key, &session->key.key); zrelease_temp_mpi_key(&S); if (ret < 0) { gnutls_assert(); return ret; } ret = _gnutls_buffer_append_mpi(data, 16, A, 0); if (ret < 0) return gnutls_assert_val(ret); _gnutls_mpi_log("SRP A: ", A); _gnutls_mpi_release(&A); return data->length; }
/* This is used for DH or ECDH key derivation. In DH for example * it is given the peers Y and our x, and calculates Y^x */ static int _wrap_nettle_pk_derive(gnutls_pk_algorithm_t algo, gnutls_datum_t * out, const gnutls_pk_params_st * priv, const gnutls_pk_params_st * pub) { int ret; switch (algo) { case GNUTLS_PK_DH: { bigint_t f, x, prime; bigint_t k = NULL, ff = NULL; unsigned int bits; f = pub->params[DH_Y]; x = priv->params[DH_X]; prime = priv->params[DH_P]; ret = _gnutls_mpi_init_multi(&k, &ff, NULL); if (ret < 0) return gnutls_assert_val(ret); ret = _gnutls_mpi_modm(ff, f, prime); if (ret < 0) { gnutls_assert(); goto dh_cleanup; } ret = _gnutls_mpi_add_ui(ff, ff, 1); if (ret < 0) { gnutls_assert(); goto dh_cleanup; } /* check if f==0,1,p-1. * or (ff=f+1) equivalently ff==1,2,p */ if ((_gnutls_mpi_cmp_ui(ff, 2) == 0) || (_gnutls_mpi_cmp_ui(ff, 1) == 0) || (_gnutls_mpi_cmp(ff, prime) == 0)) { gnutls_assert(); ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; goto dh_cleanup; } /* prevent denial of service */ bits = _gnutls_mpi_get_nbits(prime); if (bits == 0 || bits > MAX_DH_BITS) { gnutls_assert(); ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; goto dh_cleanup; } ret = _gnutls_mpi_powm(k, f, x, prime); if (ret < 0) { gnutls_assert(); goto dh_cleanup; } ret = _gnutls_mpi_dprint(k, out); if (ret < 0) { gnutls_assert(); goto dh_cleanup; } ret = 0; dh_cleanup: _gnutls_mpi_release(&ff); zrelease_temp_mpi_key(&k); if (ret < 0) goto cleanup; break; } case GNUTLS_PK_EC: { struct ecc_scalar ecc_priv; struct ecc_point ecc_pub; const struct ecc_curve *curve; out->data = NULL; curve = get_supported_curve(priv->flags); if (curve == NULL) return gnutls_assert_val (GNUTLS_E_ECC_UNSUPPORTED_CURVE); ret = _ecc_params_to_pubkey(pub, &ecc_pub, curve); if (ret < 0) return gnutls_assert_val(ret); ret = _ecc_params_to_privkey(priv, &ecc_priv, curve); if (ret < 0) { ecc_point_clear(&ecc_pub); return gnutls_assert_val(ret); } out->size = gnutls_ecc_curve_get_size(priv->flags); /*ecc_size(curve)*sizeof(mp_limb_t); */ out->data = gnutls_malloc(out->size); if (out->data == NULL) { ret = gnutls_assert_val (GNUTLS_E_MEMORY_ERROR); goto ecc_cleanup; } ecc_shared_secret(&ecc_priv, &ecc_pub, out->data, out->size); ecc_cleanup: ecc_point_clear(&ecc_pub); ecc_scalar_zclear(&ecc_priv); if (ret < 0) goto cleanup; break; } default: gnutls_assert(); ret = GNUTLS_E_INTERNAL_ERROR; goto cleanup; } ret = 0; cleanup: return ret; }