259 lines
6.8 KiB
C
259 lines
6.8 KiB
C
/* common.c
|
|
*
|
|
* Copyright (C) 2021 wolfSSL Inc.
|
|
*
|
|
* This file is part of wolfSSL.
|
|
*
|
|
* wolfSSL 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 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* wolfSSL 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 this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|
*/
|
|
|
|
#include "common.h"
|
|
|
|
volatile int keep_running = 1;
|
|
|
|
static isotp_wolfssl_ctx isotp_ctx;
|
|
|
|
|
|
struct can_info {
|
|
int sock;
|
|
canid_t arbitration;
|
|
canid_t remote_arbitration;
|
|
};
|
|
|
|
struct can_info can_con_info;
|
|
|
|
/* Function callback for wolfSSL to add delays to messages when a receiver
|
|
* requests it*/
|
|
void can_delay(int microseconds)
|
|
{
|
|
usleep(microseconds);
|
|
}
|
|
|
|
void sig_handle(int dummy);
|
|
|
|
/* Function callback for wolfSSL to send a CAN bus frame of up to 8 bytes */
|
|
int can_receive(struct isotp_can_data *data, void *arg, int timeout) {
|
|
int nbytes;
|
|
int ret;
|
|
struct can_info *info = ((struct can_info*)arg);
|
|
struct can_frame frame;
|
|
struct pollfd p[1];
|
|
|
|
p[0].fd = info->sock;
|
|
p[0].events = POLLIN;
|
|
|
|
/* Poll for new data */
|
|
ret = poll(p, 1, timeout);
|
|
|
|
if (ret <= 0) {
|
|
return ret;
|
|
}
|
|
|
|
/* Read in the frame data */
|
|
nbytes = read(info->sock, &frame, sizeof(struct can_frame));
|
|
if (nbytes <= 0) {
|
|
return nbytes;
|
|
}
|
|
memcpy(data->data, frame.data, frame.can_dlc);
|
|
data->length = frame.can_dlc;
|
|
return ret;
|
|
}
|
|
|
|
/* Function callback for wolfSSL to send a CAN bus frame of up to 8 bytes */
|
|
int can_send(struct isotp_can_data *data, void *arg)
|
|
{
|
|
struct can_info *info = ((struct can_info*)arg);
|
|
struct can_frame frame;
|
|
memcpy(frame.data, data->data, data->length);
|
|
frame.can_dlc = data->length;
|
|
frame.can_id = info->arbitration;
|
|
return write(info->sock, &frame, sizeof(struct can_frame));
|
|
}
|
|
|
|
|
|
/* Connect to the CAN bus */
|
|
int can_connect(const char *address, uint16_t filter)
|
|
{
|
|
struct sockaddr_can addr;
|
|
struct ifreq ifr;
|
|
/* Setup a CAN bus ID filter so that the kernel space filters out messages
|
|
* we don't need. This is faster than userspace doing it */
|
|
struct can_filter rfilter[1];
|
|
int sock = -1;
|
|
|
|
rfilter[0].can_id = filter;
|
|
rfilter[0].can_mask = 0xFFF;
|
|
|
|
if ((sock = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
|
|
perror("Socket open error\n");
|
|
return -1;
|
|
}
|
|
/* Set the filter */
|
|
setsockopt(sock, SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter, sizeof(rfilter));
|
|
|
|
strcpy(ifr.ifr_name, address);
|
|
ioctl(sock, SIOCGIFINDEX, &ifr);
|
|
|
|
memset(&addr, 0, sizeof(addr));
|
|
addr.can_family = AF_CAN;
|
|
addr.can_ifindex = ifr.ifr_ifindex;
|
|
if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
|
perror("Bind error\n");
|
|
return -1;
|
|
}
|
|
|
|
return sock;
|
|
}
|
|
|
|
void can_close()
|
|
{
|
|
close(can_con_info.sock);
|
|
}
|
|
|
|
void close_ssl(WOLFSSL_CTX *ctx, WOLFSSL *ssl)
|
|
{
|
|
if (ssl) {
|
|
int ret = WOLFSSL_SHUTDOWN_NOT_DONE;
|
|
while (ret == WOLFSSL_SHUTDOWN_NOT_DONE) {
|
|
ret = wolfSSL_shutdown(ssl);
|
|
}
|
|
if (ret != WOLFSSL_SUCCESS) {
|
|
char buffer[ERR_MSG_LEN];
|
|
int err = wolfSSL_get_error(ssl, ret);
|
|
fprintf(stderr, "Error shutting down TLS connection: %d, %s",
|
|
err, wolfSSL_ERR_error_string(err, buffer));
|
|
return;
|
|
}
|
|
}
|
|
can_close();
|
|
|
|
wolfSSL_free(ssl);
|
|
wolfSSL_CTX_free(ctx);
|
|
wolfSSL_Cleanup();
|
|
}
|
|
|
|
void sig_handle(int dummy)
|
|
{
|
|
(void) dummy;
|
|
keep_running = 0;
|
|
}
|
|
|
|
int setup_connection(const char *interface, int local_id, int remote_id)
|
|
{
|
|
int sock;
|
|
struct sigaction sa = { .sa_handler = sig_handle, /* .sa_flags = 0 */ };
|
|
sigaction(SIGINT, &sa, 0);
|
|
|
|
wolfSSL_Init();
|
|
|
|
/* Connect to CAN bus provided on command line, filter out everything
|
|
* except for the remote CAN ID */
|
|
sock = can_connect(interface, remote_id);
|
|
if (sock < 1) {
|
|
return -1;
|
|
}
|
|
can_con_info.sock = sock;
|
|
can_con_info.arbitration = local_id;
|
|
return 0;
|
|
}
|
|
|
|
int setup_ssl(enum service_type type, WOLFSSL_CTX **new_ctx,
|
|
WOLFSSL_METHOD **new_method, WOLFSSL **new_ssl)
|
|
{
|
|
int ret;
|
|
WOLFSSL_CTX *ctx = NULL;
|
|
WOLFSSL_METHOD* method = NULL;
|
|
WOLFSSL* ssl = NULL;
|
|
char *receive_buffer = malloc(ISOTP_DEFAULT_BUFFER_SIZE);
|
|
|
|
if (type == SERVICE_TYPE_CLIENT) {
|
|
method = wolfTLSv1_3_client_method();
|
|
} else {
|
|
method = wolfTLSv1_3_server_method();
|
|
}
|
|
|
|
if (!method) {
|
|
fprintf(stderr, "Could not init wolfSSL method\n");
|
|
return -1;
|
|
}
|
|
|
|
ctx = wolfSSL_CTX_new(method);
|
|
if (!ctx) {
|
|
fprintf(stderr, "Could not init wolfSSL context\n");
|
|
close_ssl(NULL, NULL);
|
|
return -1;
|
|
}
|
|
|
|
wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_NONE, NULL);
|
|
|
|
if (type == SERVICE_TYPE_CLIENT) {
|
|
ret = wolfSSL_CTX_load_verify_locations(ctx, "client.pem", NULL);
|
|
} else {
|
|
ret = wolfSSL_CTX_use_certificate_file(ctx, "server.pem",
|
|
WOLFSSL_FILETYPE_PEM);
|
|
}
|
|
|
|
if (ret != WOLFSSL_SUCCESS) {
|
|
fprintf(stderr, "ERROR: failed to load cert, "
|
|
"please check the file.\n");
|
|
close_ssl(ctx, NULL);
|
|
return -1;
|
|
}
|
|
|
|
if (type == SERVICE_TYPE_SERVER) {
|
|
if ((ret = wolfSSL_CTX_use_PrivateKey_file(ctx, "server.key",
|
|
WOLFSSL_FILETYPE_PEM)) != WOLFSSL_SUCCESS) {
|
|
fprintf(stderr, "ERROR: failed to load key file, "
|
|
"please check the file.\n");
|
|
close_ssl(ctx, NULL);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
ssl = wolfSSL_new(ctx);
|
|
if (!ssl) {
|
|
fprintf(stderr, "Could not init wolfSSL\n");
|
|
close_ssl(ctx, NULL);
|
|
return -1;
|
|
}
|
|
|
|
wolfSSL_SetIO_ISOTP(ssl, &isotp_ctx, can_receive, can_send, can_delay, 0,
|
|
receive_buffer, ISOTP_DEFAULT_BUFFER_SIZE, &can_con_info);
|
|
|
|
if (type == SERVICE_TYPE_CLIENT) {
|
|
ret = wolfSSL_connect(ssl);
|
|
} else {
|
|
ret = wolfSSL_accept(ssl);
|
|
}
|
|
|
|
wolfSSL_set_using_nonblock(ssl, 1);
|
|
|
|
if (ret != WOLFSSL_SUCCESS) {
|
|
char buffer[ERR_MSG_LEN];
|
|
int err = wolfSSL_get_error(ssl, ret);
|
|
fprintf(stderr, "ERROR: failed to connect using wolfSSL: %d, %s\n",
|
|
err, wolfSSL_ERR_error_string(err, buffer));
|
|
close_ssl(ctx, ssl);
|
|
return -1;
|
|
}
|
|
*new_ctx = ctx;
|
|
*new_method = method;
|
|
*new_ssl = ssl;
|
|
|
|
printf("SSL handshake done!\n");
|
|
|
|
return 0;
|
|
}
|