/* This file is part of libcapwap. libcapwap is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. libcapwap is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Foobar. If not, see . */ #include #include #include #include "dtls_gnutls.h" #include "conn.h" #include "cw_log.h" #include "cw_util.h" int dtls_gnutls_init() { cw_dbg(DBG_CW_INFO,"Init SSL library - using GnuTLS %s",gnutls_check_version(NULL)); gnutls_global_init(); return 1; } int dtls_gnutls_shutdown(struct conn *conn) { /* implement it */ return 1; } void dtls_gnutls_data_destroy(struct dtls_gnutls_data *d) { free(d); } int dtls_gnutls_write(struct conn * conn, const uint8_t *buffer, int len) { struct dtls_gnutls_data * d = conn->dtls_data; int rc = gnutls_record_send(d->session,buffer,len); if ( rc < 0 ){ cw_log(LOG_ERR, "DTLS - write error: %s", gnutls_strerror(rc)); conn->dtls_error=1; return -1; } return rc; } int dtls_gnutls_read(struct conn * conn, uint8_t *buffer, int len) { uint8_t seq[8]; struct dtls_gnutls_data * d = conn->dtls_data; int rc = gnutls_record_recv_seq(d->session,buffer,len,seq); if (rc==0) { errno = ECONNRESET; return -1; } if ( rc == GNUTLS_E_AGAIN ){ errno = EAGAIN; return -1; } if ( rc < 0 ){ cw_log(LOG_ERR, "DTLS - read error: %s", gnutls_strerror(rc)); conn->dtls_error=1; return -1; } return rc; } struct dtls_gnutls_data *dtls_gnutls_data_create(struct conn *conn,int config) { struct dtls_gnutls_data *d = malloc(sizeof(struct dtls_gnutls_data)); if (!d) return 0; gnutls_certificate_allocate_credentials(&d->x509_cred); int rc; /* Set credentials */ rc = gnutls_certificate_set_x509_key_file(d->x509_cred, conn->dtls_cert_file, conn->dtls_key_file, GNUTLS_X509_FMT_PEM); if (rc < 0) { cw_log(LOG_ERR, "DTLS - Can't set cert/key: %s", gnutls_strerror(rc)); dtls_gnutls_data_destroy(d); return 0; } int bits; bits = gnutls_sec_param_to_pk_bits(GNUTLS_PK_DH, GNUTLS_SEC_PARAM_INSECURE); /* Generate Diffie-Hellman parameters - for use with DHE * kx algorithms. When short bit length is used, it might * be wise to regenerate parameters often. */ gnutls_dh_params_init(&d->dh_params); gnutls_dh_params_generate2(d->dh_params, bits); gnutls_certificate_set_dh_params(d->x509_cred, d->dh_params); /* Set ciphers */ const char *errpos; rc = gnutls_priority_init(&d->priority_cache, conn->dtls_cipher, &errpos); if (rc < 0) { cw_log(LOG_ERR, "DTLS - Can't init ciphers '%s' at '%s' : %s", conn->dtls_cipher, errpos, gnutls_strerror(rc)); dtls_gnutls_data_destroy(d); return 0; } rc = gnutls_init(&d->session, config); if (rc < 0) { cw_log(LOG_ERR, "DTLS - Can't init session: %s", gnutls_strerror(rc)); dtls_gnutls_data_destroy(d); return 0; } gnutls_transport_set_ptr(d->session, conn); rc = gnutls_priority_set(d->session, d->priority_cache); if (rc < 0) { cw_log(LOG_ERR, "DTLS - Can't set priority: %s", gnutls_strerror(rc)); dtls_gnutls_data_destroy(d); return 0; } rc = gnutls_credentials_set(d->session, GNUTLS_CRD_CERTIFICATE, d->x509_cred); if (rc < 0) { cw_log(LOG_ERR, "DTLS - Can't set credentials: %s", gnutls_strerror(rc)); dtls_gnutls_data_destroy(d); return 0; } gnutls_transport_set_pull_function(d->session, dtls_gnutls_bio_read); gnutls_transport_set_push_function(d->session, dtls_gnutls_bio_write); gnutls_transport_set_pull_timeout_function(d->session, dtls_gnutls_bio_wait); return d; }