xref: /aosp_15_r20/external/tpm2-tss/src/util/io.c (revision 758e9fba6fc9adbf15340f70c73baee7b168b1c9)
1*758e9fbaSOystein Eftevaag /* SPDX-License-Identifier: BSD-2-Clause */
2*758e9fbaSOystein Eftevaag /*
3*758e9fbaSOystein Eftevaag  * Copyright (c) 2015 - 2018 Intel Corporation
4*758e9fbaSOystein Eftevaag  * All rights reserved.
5*758e9fbaSOystein Eftevaag  */
6*758e9fbaSOystein Eftevaag #ifdef HAVE_CONFIG_H
7*758e9fbaSOystein Eftevaag #include <config.h>
8*758e9fbaSOystein Eftevaag #endif
9*758e9fbaSOystein Eftevaag 
10*758e9fbaSOystein Eftevaag #include <errno.h>
11*758e9fbaSOystein Eftevaag #include <fcntl.h>
12*758e9fbaSOystein Eftevaag #include <inttypes.h>
13*758e9fbaSOystein Eftevaag #include <limits.h>
14*758e9fbaSOystein Eftevaag #include <string.h>
15*758e9fbaSOystein Eftevaag #include <stdio.h>
16*758e9fbaSOystein Eftevaag 
17*758e9fbaSOystein Eftevaag #ifndef _WIN32
18*758e9fbaSOystein Eftevaag #include <netdb.h>
19*758e9fbaSOystein Eftevaag #include <netinet/in.h>
20*758e9fbaSOystein Eftevaag #include <unistd.h>
21*758e9fbaSOystein Eftevaag #endif
22*758e9fbaSOystein Eftevaag 
23*758e9fbaSOystein Eftevaag #include "tss2_tpm2_types.h"
24*758e9fbaSOystein Eftevaag 
25*758e9fbaSOystein Eftevaag #include "io.h"
26*758e9fbaSOystein Eftevaag #define LOGMODULE tcti
27*758e9fbaSOystein Eftevaag #include "util/log.h"
28*758e9fbaSOystein Eftevaag 
29*758e9fbaSOystein Eftevaag #define MAX_PORT_STR_LEN    sizeof("65535")
30*758e9fbaSOystein Eftevaag /*
31*758e9fbaSOystein Eftevaag  * The 'read_all' function attempts to read all of the 'size' bytes requested
32*758e9fbaSOystein Eftevaag  * from the 'fd' provided into the buffer 'data'. This function will continue
33*758e9fbaSOystein Eftevaag  * to retry after temporary failures and "short reads". It will only stop
34*758e9fbaSOystein Eftevaag  * once all of the requested data has been read, an error occurs, or EOF.
35*758e9fbaSOystein Eftevaag  * On error or EOF, the number of bytes read (if any) will be returned.
36*758e9fbaSOystein Eftevaag  */
37*758e9fbaSOystein Eftevaag ssize_t
read_all(SOCKET fd,uint8_t * data,size_t size)38*758e9fbaSOystein Eftevaag read_all (
39*758e9fbaSOystein Eftevaag     SOCKET fd,
40*758e9fbaSOystein Eftevaag     uint8_t *data,
41*758e9fbaSOystein Eftevaag     size_t size)
42*758e9fbaSOystein Eftevaag {
43*758e9fbaSOystein Eftevaag     ssize_t recvd;
44*758e9fbaSOystein Eftevaag     size_t recvd_total = 0;
45*758e9fbaSOystein Eftevaag 
46*758e9fbaSOystein Eftevaag     LOG_DEBUG ("reading %zu bytes from fd %d to buffer at 0x%" PRIxPTR,
47*758e9fbaSOystein Eftevaag                size, fd, (uintptr_t)data);
48*758e9fbaSOystein Eftevaag     do {
49*758e9fbaSOystein Eftevaag #ifdef _WIN32
50*758e9fbaSOystein Eftevaag         TEMP_RETRY (recvd, recv (fd, (char *) &data [recvd_total], size, 0));
51*758e9fbaSOystein Eftevaag         if (recvd < 0) {
52*758e9fbaSOystein Eftevaag             LOG_WARNING ("read on fd %d failed with errno %d: %s",
53*758e9fbaSOystein Eftevaag                          fd, WSAGetLastError(), strerror (WSAGetLastError()));
54*758e9fbaSOystein Eftevaag             return recvd_total;
55*758e9fbaSOystein Eftevaag         }
56*758e9fbaSOystein Eftevaag #else
57*758e9fbaSOystein Eftevaag         TEMP_RETRY (recvd, read (fd, &data [recvd_total], size));
58*758e9fbaSOystein Eftevaag         if (recvd < 0) {
59*758e9fbaSOystein Eftevaag             LOG_WARNING ("read on fd %d failed with errno %d: %s",
60*758e9fbaSOystein Eftevaag                          fd, errno, strerror (errno));
61*758e9fbaSOystein Eftevaag             return recvd_total;
62*758e9fbaSOystein Eftevaag         }
63*758e9fbaSOystein Eftevaag #endif
64*758e9fbaSOystein Eftevaag         if (recvd == 0) {
65*758e9fbaSOystein Eftevaag             LOG_WARNING ("Attempted read %zu bytes from fd %d, but EOF "
66*758e9fbaSOystein Eftevaag                          "returned", size, fd);
67*758e9fbaSOystein Eftevaag             return recvd_total;
68*758e9fbaSOystein Eftevaag         }
69*758e9fbaSOystein Eftevaag         LOGBLOB_DEBUG (&data [recvd_total], recvd, "read %zd bytes from fd %d:", recvd, fd);
70*758e9fbaSOystein Eftevaag         recvd_total += recvd;
71*758e9fbaSOystein Eftevaag         size -= recvd;
72*758e9fbaSOystein Eftevaag     } while (size > 0);
73*758e9fbaSOystein Eftevaag 
74*758e9fbaSOystein Eftevaag     return recvd_total;
75*758e9fbaSOystein Eftevaag }
76*758e9fbaSOystein Eftevaag 
77*758e9fbaSOystein Eftevaag ssize_t
write_all(SOCKET fd,const uint8_t * buf,size_t size)78*758e9fbaSOystein Eftevaag write_all (
79*758e9fbaSOystein Eftevaag     SOCKET fd,
80*758e9fbaSOystein Eftevaag     const uint8_t *buf,
81*758e9fbaSOystein Eftevaag     size_t size)
82*758e9fbaSOystein Eftevaag {
83*758e9fbaSOystein Eftevaag     ssize_t written = 0;
84*758e9fbaSOystein Eftevaag     size_t written_total = 0;
85*758e9fbaSOystein Eftevaag 
86*758e9fbaSOystein Eftevaag     do {
87*758e9fbaSOystein Eftevaag         LOG_DEBUG("writing %zu bytes starting at 0x%" PRIxPTR " to fd %d",
88*758e9fbaSOystein Eftevaag                   size - written_total,
89*758e9fbaSOystein Eftevaag                   (uintptr_t)(buf + written_total),
90*758e9fbaSOystein Eftevaag                   fd);
91*758e9fbaSOystein Eftevaag #ifdef _WIN32
92*758e9fbaSOystein Eftevaag         TEMP_RETRY (written, send (fd,
93*758e9fbaSOystein Eftevaag                                    (const char*)&buf [written_total],
94*758e9fbaSOystein Eftevaag                                    size - written_total, 0));
95*758e9fbaSOystein Eftevaag #else
96*758e9fbaSOystein Eftevaag          TEMP_RETRY (written, write (fd,
97*758e9fbaSOystein Eftevaag                                      (const char*)&buf [written_total],
98*758e9fbaSOystein Eftevaag                                      size - written_total));
99*758e9fbaSOystein Eftevaag #endif
100*758e9fbaSOystein Eftevaag         if (written >= 0) {
101*758e9fbaSOystein Eftevaag             LOG_DEBUG ("wrote %zd bytes to fd %d", written, fd);
102*758e9fbaSOystein Eftevaag             written_total += (size_t)written;
103*758e9fbaSOystein Eftevaag         } else {
104*758e9fbaSOystein Eftevaag #ifdef _WIN32
105*758e9fbaSOystein Eftevaag             LOG_ERROR ("failed to write to fd %d: %s", fd, strerror (WSAGetLastError()));
106*758e9fbaSOystein Eftevaag #else
107*758e9fbaSOystein Eftevaag             LOG_ERROR ("failed to write to fd %d: %s", fd, strerror (errno));
108*758e9fbaSOystein Eftevaag #endif
109*758e9fbaSOystein Eftevaag             return written_total;
110*758e9fbaSOystein Eftevaag         }
111*758e9fbaSOystein Eftevaag     } while (written_total < size);
112*758e9fbaSOystein Eftevaag 
113*758e9fbaSOystein Eftevaag     return (ssize_t)written_total;
114*758e9fbaSOystein Eftevaag }
115*758e9fbaSOystein Eftevaag 
116*758e9fbaSOystein Eftevaag ssize_t
socket_recv_buf(SOCKET sock,uint8_t * data,size_t size)117*758e9fbaSOystein Eftevaag socket_recv_buf (
118*758e9fbaSOystein Eftevaag     SOCKET sock,
119*758e9fbaSOystein Eftevaag     uint8_t *data,
120*758e9fbaSOystein Eftevaag     size_t size)
121*758e9fbaSOystein Eftevaag {
122*758e9fbaSOystein Eftevaag     return read_all (sock, data, size);
123*758e9fbaSOystein Eftevaag }
124*758e9fbaSOystein Eftevaag 
125*758e9fbaSOystein Eftevaag TSS2_RC
socket_xmit_buf(SOCKET sock,const void * buf,size_t size)126*758e9fbaSOystein Eftevaag socket_xmit_buf (
127*758e9fbaSOystein Eftevaag     SOCKET sock,
128*758e9fbaSOystein Eftevaag     const void *buf,
129*758e9fbaSOystein Eftevaag     size_t size)
130*758e9fbaSOystein Eftevaag {
131*758e9fbaSOystein Eftevaag     int ret;
132*758e9fbaSOystein Eftevaag 
133*758e9fbaSOystein Eftevaag     LOGBLOB_DEBUG (buf, size, "Writing %zu bytes to socket %d:", size, sock);
134*758e9fbaSOystein Eftevaag     ret = write_all (sock, buf, size);
135*758e9fbaSOystein Eftevaag     if (ret < (ssize_t) size) {
136*758e9fbaSOystein Eftevaag #ifdef _WIN32
137*758e9fbaSOystein Eftevaag         LOG_ERROR ("write to fd %d failed, errno %d: %s", sock, WSAGetLastError(), strerror (WSAGetLastError()));
138*758e9fbaSOystein Eftevaag #else
139*758e9fbaSOystein Eftevaag         LOG_ERROR ("write to fd %d failed, errno %d: %s", sock, errno, strerror (errno));
140*758e9fbaSOystein Eftevaag #endif
141*758e9fbaSOystein Eftevaag         return TSS2_TCTI_RC_IO_ERROR;
142*758e9fbaSOystein Eftevaag     }
143*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
144*758e9fbaSOystein Eftevaag }
145*758e9fbaSOystein Eftevaag 
146*758e9fbaSOystein Eftevaag TSS2_RC
socket_close(SOCKET * socket)147*758e9fbaSOystein Eftevaag socket_close (
148*758e9fbaSOystein Eftevaag     SOCKET *socket)
149*758e9fbaSOystein Eftevaag {
150*758e9fbaSOystein Eftevaag     int ret;
151*758e9fbaSOystein Eftevaag 
152*758e9fbaSOystein Eftevaag     if (socket == NULL) {
153*758e9fbaSOystein Eftevaag         return TSS2_TCTI_RC_BAD_REFERENCE;
154*758e9fbaSOystein Eftevaag     }
155*758e9fbaSOystein Eftevaag     if (*socket == INVALID_SOCKET) {
156*758e9fbaSOystein Eftevaag         return TSS2_RC_SUCCESS;
157*758e9fbaSOystein Eftevaag     }
158*758e9fbaSOystein Eftevaag #ifdef _WIN32
159*758e9fbaSOystein Eftevaag     ret = closesocket (*socket);
160*758e9fbaSOystein Eftevaag     WSACleanup();
161*758e9fbaSOystein Eftevaag     if (ret == SOCKET_ERROR) {
162*758e9fbaSOystein Eftevaag         LOG_WARNING ("Failed to close SOCKET %d. errno %d: %s",
163*758e9fbaSOystein Eftevaag                      *socket, WSAGetLastError(), strerror (WSAGetLastError()));
164*758e9fbaSOystein Eftevaag         return TSS2_TCTI_RC_IO_ERROR;
165*758e9fbaSOystein Eftevaag     }
166*758e9fbaSOystein Eftevaag #else
167*758e9fbaSOystein Eftevaag     ret = close (*socket);
168*758e9fbaSOystein Eftevaag     if (ret == SOCKET_ERROR) {
169*758e9fbaSOystein Eftevaag         LOG_WARNING ("Failed to close SOCKET %d. errno %d: %s",
170*758e9fbaSOystein Eftevaag                      *socket, errno, strerror (errno));
171*758e9fbaSOystein Eftevaag         return TSS2_TCTI_RC_IO_ERROR;
172*758e9fbaSOystein Eftevaag     }
173*758e9fbaSOystein Eftevaag #endif
174*758e9fbaSOystein Eftevaag     *socket = INVALID_SOCKET;
175*758e9fbaSOystein Eftevaag 
176*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
177*758e9fbaSOystein Eftevaag }
178*758e9fbaSOystein Eftevaag 
179*758e9fbaSOystein Eftevaag TSS2_RC
socket_connect(const char * hostname,uint16_t port,SOCKET * sock)180*758e9fbaSOystein Eftevaag socket_connect (
181*758e9fbaSOystein Eftevaag     const char *hostname,
182*758e9fbaSOystein Eftevaag     uint16_t port,
183*758e9fbaSOystein Eftevaag     SOCKET *sock)
184*758e9fbaSOystein Eftevaag {
185*758e9fbaSOystein Eftevaag     static const struct addrinfo hints = { .ai_socktype = SOCK_STREAM,
186*758e9fbaSOystein Eftevaag         .ai_family = AF_UNSPEC, .ai_protocol = IPPROTO_TCP};
187*758e9fbaSOystein Eftevaag     struct addrinfo *retp = NULL;
188*758e9fbaSOystein Eftevaag     struct addrinfo *p;
189*758e9fbaSOystein Eftevaag     char port_str[MAX_PORT_STR_LEN];
190*758e9fbaSOystein Eftevaag     int ret = 0;
191*758e9fbaSOystein Eftevaag #ifdef _WIN32
192*758e9fbaSOystein Eftevaag     char host_buff[_HOST_NAME_MAX];
193*758e9fbaSOystein Eftevaag     const char *h = hostname;
194*758e9fbaSOystein Eftevaag     WSADATA wsaData;
195*758e9fbaSOystein Eftevaag     int iResult;
196*758e9fbaSOystein Eftevaag     iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
197*758e9fbaSOystein Eftevaag     if (iResult != 0) {
198*758e9fbaSOystein Eftevaag         LOG_WARNING("WSAStartup failed: %d", iResult);
199*758e9fbaSOystein Eftevaag         return TSS2_TCTI_RC_IO_ERROR;
200*758e9fbaSOystein Eftevaag     }
201*758e9fbaSOystein Eftevaag #else
202*758e9fbaSOystein Eftevaag     char host_buff[_HOST_NAME_MAX] __attribute__((unused));
203*758e9fbaSOystein Eftevaag     const char *h __attribute__((unused)) = hostname;
204*758e9fbaSOystein Eftevaag #endif
205*758e9fbaSOystein Eftevaag 
206*758e9fbaSOystein Eftevaag     if (hostname == NULL || sock == NULL) {
207*758e9fbaSOystein Eftevaag         return TSS2_TCTI_RC_BAD_REFERENCE;
208*758e9fbaSOystein Eftevaag     }
209*758e9fbaSOystein Eftevaag 
210*758e9fbaSOystein Eftevaag     ret = snprintf(port_str, sizeof(port_str), "%u", port);
211*758e9fbaSOystein Eftevaag     if (ret < 0)
212*758e9fbaSOystein Eftevaag         return TSS2_TCTI_RC_BAD_VALUE;
213*758e9fbaSOystein Eftevaag 
214*758e9fbaSOystein Eftevaag 
215*758e9fbaSOystein Eftevaag     LOG_DEBUG ("Resolving host %s", hostname);
216*758e9fbaSOystein Eftevaag     ret = getaddrinfo (hostname, port_str, &hints, &retp);
217*758e9fbaSOystein Eftevaag     if (ret != 0) {
218*758e9fbaSOystein Eftevaag         LOG_WARNING ("Host %s does not resolve to a valid address: %d: %s",
219*758e9fbaSOystein Eftevaag             hostname, ret, gai_strerror(ret));
220*758e9fbaSOystein Eftevaag         return TSS2_TCTI_RC_IO_ERROR;
221*758e9fbaSOystein Eftevaag     }
222*758e9fbaSOystein Eftevaag 
223*758e9fbaSOystein Eftevaag     for (p = retp; p != NULL; p = p->ai_next) {
224*758e9fbaSOystein Eftevaag         *sock = socket (p->ai_family, SOCK_STREAM, 0);
225*758e9fbaSOystein Eftevaag         void *sockaddr;
226*758e9fbaSOystein Eftevaag 
227*758e9fbaSOystein Eftevaag         if (*sock == INVALID_SOCKET)
228*758e9fbaSOystein Eftevaag             continue;
229*758e9fbaSOystein Eftevaag 
230*758e9fbaSOystein Eftevaag         if (p->ai_family == AF_INET)
231*758e9fbaSOystein Eftevaag             sockaddr = &((struct sockaddr_in*)p->ai_addr)->sin_addr;
232*758e9fbaSOystein Eftevaag         else
233*758e9fbaSOystein Eftevaag             sockaddr = &((struct sockaddr_in6*)p->ai_addr)->sin6_addr;
234*758e9fbaSOystein Eftevaag 
235*758e9fbaSOystein Eftevaag         h = inet_ntop(p->ai_family, sockaddr, host_buff, sizeof(host_buff));
236*758e9fbaSOystein Eftevaag 
237*758e9fbaSOystein Eftevaag         if (h == NULL)
238*758e9fbaSOystein Eftevaag             h = hostname;
239*758e9fbaSOystein Eftevaag 
240*758e9fbaSOystein Eftevaag         LOG_DEBUG ("Attempting TCP connection to host %s, port %s",
241*758e9fbaSOystein Eftevaag             h, port_str);
242*758e9fbaSOystein Eftevaag         if (connect (*sock, p->ai_addr, p->ai_addrlen) != SOCKET_ERROR)
243*758e9fbaSOystein Eftevaag             break; /* socket connected OK */
244*758e9fbaSOystein Eftevaag         socket_close (sock);
245*758e9fbaSOystein Eftevaag     }
246*758e9fbaSOystein Eftevaag     freeaddrinfo (retp);
247*758e9fbaSOystein Eftevaag     if (p == NULL) {
248*758e9fbaSOystein Eftevaag #ifdef _WIN32
249*758e9fbaSOystein Eftevaag         LOG_WARNING ("Failed to connect to host %s, port %s: errno %d: %s",
250*758e9fbaSOystein Eftevaag                       h, port_str, WSAGetLastError(), strerror (WSAGetLastError()));
251*758e9fbaSOystein Eftevaag #else
252*758e9fbaSOystein Eftevaag         LOG_WARNING ("Failed to connect to host %s, port %s: errno %d: %s",
253*758e9fbaSOystein Eftevaag                      h, port_str, errno, strerror (errno));
254*758e9fbaSOystein Eftevaag #endif
255*758e9fbaSOystein Eftevaag 
256*758e9fbaSOystein Eftevaag         return TSS2_TCTI_RC_IO_ERROR;
257*758e9fbaSOystein Eftevaag     }
258*758e9fbaSOystein Eftevaag 
259*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
260*758e9fbaSOystein Eftevaag }
261