2018-09-06 10:28:55 +02:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2018 Nordic Semiconductor ASA
|
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
*/
|
|
|
|
|
|
|
|
/** @file mqtt_transport_socket_tls.h
|
|
|
|
*
|
|
|
|
* @brief Internal functions to handle transport over TLS socket.
|
|
|
|
*/
|
|
|
|
|
2022-05-06 11:12:04 +02:00
|
|
|
#include <zephyr/logging/log.h>
|
2018-11-30 11:54:56 +01:00
|
|
|
LOG_MODULE_REGISTER(net_mqtt_sock_tls, CONFIG_MQTT_LOG_LEVEL);
|
2018-09-06 10:28:55 +02:00
|
|
|
|
|
|
|
#include <errno.h>
|
2022-05-06 11:12:04 +02:00
|
|
|
#include <zephyr/net/socket.h>
|
|
|
|
#include <zephyr/net/mqtt.h>
|
2018-09-06 10:28:55 +02:00
|
|
|
|
|
|
|
#include "mqtt_os.h"
|
|
|
|
|
|
|
|
int mqtt_client_tls_connect(struct mqtt_client *client)
|
|
|
|
{
|
|
|
|
const struct sockaddr *broker = client->broker;
|
|
|
|
struct mqtt_sec_config *tls_config = &client->transport.tls.config;
|
|
|
|
int ret;
|
|
|
|
|
2020-09-04 13:21:50 +02:00
|
|
|
client->transport.tls.sock = zsock_socket(broker->sa_family,
|
|
|
|
SOCK_STREAM, IPPROTO_TLS_1_2);
|
2018-09-06 10:28:55 +02:00
|
|
|
if (client->transport.tls.sock < 0) {
|
|
|
|
return -errno;
|
|
|
|
}
|
|
|
|
|
2022-04-06 12:37:11 +02:00
|
|
|
NET_DBG("Created socket %d", client->transport.tls.sock);
|
2018-09-06 10:28:55 +02:00
|
|
|
|
2019-08-01 15:09:29 +02:00
|
|
|
#if defined(CONFIG_SOCKS)
|
|
|
|
if (client->transport.proxy.addrlen != 0) {
|
|
|
|
ret = setsockopt(client->transport.tls.sock,
|
|
|
|
SOL_SOCKET, SO_SOCKS5,
|
|
|
|
&client->transport.proxy.addr,
|
|
|
|
client->transport.proxy.addrlen);
|
|
|
|
if (ret < 0) {
|
2021-12-01 12:48:48 +01:00
|
|
|
goto error;
|
2019-08-01 15:09:29 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2018-09-06 10:28:55 +02:00
|
|
|
/* Set secure socket options. */
|
2020-09-04 13:21:50 +02:00
|
|
|
ret = zsock_setsockopt(client->transport.tls.sock, SOL_TLS, TLS_PEER_VERIFY,
|
|
|
|
&tls_config->peer_verify,
|
|
|
|
sizeof(tls_config->peer_verify));
|
2018-09-06 10:28:55 +02:00
|
|
|
if (ret < 0) {
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tls_config->cipher_list != NULL && tls_config->cipher_count > 0) {
|
2020-09-04 13:21:50 +02:00
|
|
|
ret = zsock_setsockopt(client->transport.tls.sock, SOL_TLS,
|
|
|
|
TLS_CIPHERSUITE_LIST, tls_config->cipher_list,
|
|
|
|
sizeof(int) * tls_config->cipher_count);
|
2018-09-06 10:28:55 +02:00
|
|
|
if (ret < 0) {
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-10 09:13:20 +01:00
|
|
|
if (tls_config->sec_tag_list != NULL && tls_config->sec_tag_count > 0) {
|
2020-09-04 13:21:50 +02:00
|
|
|
ret = zsock_setsockopt(client->transport.tls.sock, SOL_TLS,
|
|
|
|
TLS_SEC_TAG_LIST, tls_config->sec_tag_list,
|
|
|
|
sizeof(sec_tag_t) * tls_config->sec_tag_count);
|
2018-09-06 10:28:55 +02:00
|
|
|
if (ret < 0) {
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-27 19:29:33 +01:00
|
|
|
#if defined(CONFIG_MQTT_LIB_TLS_USE_ALPN)
|
|
|
|
if (tls_config->alpn_protocol_name_list != NULL &&
|
|
|
|
tls_config->alpn_protocol_name_count > 0) {
|
|
|
|
ret = zsock_setsockopt(client->transport.tls.sock, SOL_TLS,
|
|
|
|
TLS_ALPN_LIST, tls_config->alpn_protocol_name_list,
|
|
|
|
sizeof(const char *) * tls_config->alpn_protocol_name_count);
|
|
|
|
if (ret < 0) {
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2018-09-06 10:28:55 +02:00
|
|
|
if (tls_config->hostname) {
|
2020-09-04 13:21:50 +02:00
|
|
|
ret = zsock_setsockopt(client->transport.tls.sock, SOL_TLS,
|
|
|
|
TLS_HOSTNAME, tls_config->hostname,
|
2023-01-26 17:08:04 +01:00
|
|
|
strlen(tls_config->hostname) + 1);
|
2018-09-06 10:28:55 +02:00
|
|
|
if (ret < 0) {
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-19 09:46:33 +01:00
|
|
|
if (tls_config->cert_nocopy != TLS_CERT_NOCOPY_NONE) {
|
|
|
|
ret = zsock_setsockopt(client->transport.tls.sock, SOL_TLS,
|
|
|
|
TLS_CERT_NOCOPY, &tls_config->cert_nocopy,
|
|
|
|
sizeof(tls_config->cert_nocopy));
|
|
|
|
if (ret < 0) {
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-06 10:28:55 +02:00
|
|
|
size_t peer_addr_size = sizeof(struct sockaddr_in6);
|
|
|
|
|
|
|
|
if (broker->sa_family == AF_INET) {
|
|
|
|
peer_addr_size = sizeof(struct sockaddr_in);
|
|
|
|
}
|
|
|
|
|
2020-09-04 13:21:50 +02:00
|
|
|
ret = zsock_connect(client->transport.tls.sock, client->broker,
|
|
|
|
peer_addr_size);
|
2018-09-06 10:28:55 +02:00
|
|
|
if (ret < 0) {
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2022-04-06 12:37:11 +02:00
|
|
|
NET_DBG("Connect completed");
|
2018-09-06 10:28:55 +02:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
error:
|
2020-09-04 13:21:50 +02:00
|
|
|
(void) zsock_close(client->transport.tls.sock);
|
2018-09-06 10:28:55 +02:00
|
|
|
return -errno;
|
|
|
|
}
|
|
|
|
|
2020-05-27 18:26:57 +02:00
|
|
|
int mqtt_client_tls_write(struct mqtt_client *client, const uint8_t *data,
|
|
|
|
uint32_t datalen)
|
2018-09-06 10:28:55 +02:00
|
|
|
{
|
2020-05-27 18:26:57 +02:00
|
|
|
uint32_t offset = 0U;
|
2018-09-06 10:28:55 +02:00
|
|
|
int ret;
|
|
|
|
|
|
|
|
while (offset < datalen) {
|
2020-09-04 13:21:50 +02:00
|
|
|
ret = zsock_send(client->transport.tls.sock, data + offset,
|
|
|
|
datalen - offset, 0);
|
2018-09-06 10:28:55 +02:00
|
|
|
if (ret < 0) {
|
|
|
|
return -errno;
|
|
|
|
}
|
|
|
|
|
|
|
|
offset += ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-02-12 15:25:08 +01:00
|
|
|
int mqtt_client_tls_write_msg(struct mqtt_client *client,
|
|
|
|
const struct msghdr *message)
|
|
|
|
{
|
2021-09-23 16:22:46 +02:00
|
|
|
int ret, i;
|
|
|
|
size_t offset = 0;
|
|
|
|
size_t total_len = 0;
|
2020-02-12 15:25:08 +01:00
|
|
|
|
2021-09-23 16:22:46 +02:00
|
|
|
for (i = 0; i < message->msg_iovlen; i++) {
|
|
|
|
total_len += message->msg_iov[i].iov_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (offset < total_len) {
|
|
|
|
ret = zsock_sendmsg(client->transport.tls.sock, message, 0);
|
|
|
|
if (ret < 0) {
|
|
|
|
return -errno;
|
|
|
|
}
|
|
|
|
|
|
|
|
offset += ret;
|
|
|
|
if (offset >= total_len) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Update msghdr for the next iteration. */
|
|
|
|
for (i = 0; i < message->msg_iovlen; i++) {
|
|
|
|
if (ret < message->msg_iov[i].iov_len) {
|
|
|
|
message->msg_iov[i].iov_len -= ret;
|
|
|
|
message->msg_iov[i].iov_base =
|
|
|
|
(uint8_t *)message->msg_iov[i].iov_base + ret;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret -= message->msg_iov[i].iov_len;
|
|
|
|
message->msg_iov[i].iov_len = 0;
|
|
|
|
}
|
2020-02-12 15:25:08 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-05-27 18:26:57 +02:00
|
|
|
int mqtt_client_tls_read(struct mqtt_client *client, uint8_t *data, uint32_t buflen,
|
2019-02-05 12:52:40 +01:00
|
|
|
bool shall_block)
|
2018-09-06 10:28:55 +02:00
|
|
|
{
|
2019-02-05 12:52:40 +01:00
|
|
|
int flags = 0;
|
2018-09-06 10:28:55 +02:00
|
|
|
int ret;
|
|
|
|
|
2019-02-05 12:52:40 +01:00
|
|
|
if (!shall_block) {
|
2020-09-04 13:21:50 +02:00
|
|
|
flags |= ZSOCK_MSG_DONTWAIT;
|
2019-02-05 12:52:40 +01:00
|
|
|
}
|
|
|
|
|
2020-09-04 13:21:50 +02:00
|
|
|
ret = zsock_recv(client->transport.tls.sock, data, buflen, flags);
|
2018-09-06 10:28:55 +02:00
|
|
|
if (ret < 0) {
|
|
|
|
return -errno;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int mqtt_client_tls_disconnect(struct mqtt_client *client)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
2022-04-06 12:37:11 +02:00
|
|
|
NET_INFO("Closing socket %d", client->transport.tls.sock);
|
2020-09-04 13:21:50 +02:00
|
|
|
ret = zsock_close(client->transport.tls.sock);
|
2018-09-06 10:28:55 +02:00
|
|
|
if (ret < 0) {
|
|
|
|
return -errno;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|