Rewrite some read/write loops for readability
[platform/core/security/tef-simulator.git] / ssflib / src / ssf_client.cpp
1 /**
2  * Copyright (c) 2015-2017 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16
17 /**
18  * @file
19  * @author Cheryl (cb), cheryl.b@samsung.com
20  * @brief  SSF client functions
21  */
22
23
24 /*-----------------------------------------------------------------------------
25  *  Include files
26  *-----------------------------------------------------------------------------*/
27 #include "teestub_command_data.h"
28 #include "tee_internal_api.h"
29 #include <errno.h>
30 #include <assert.h>
31 #include "ssf_client.h"
32 #include <unistd.h>
33 #include <config.h>
34
35 /*-----------------------------------------------------------------------------
36  *  MACROS
37  *-----------------------------------------------------------------------------*/
38
39 /*-----------------------------------------------------------------------------
40  *  local functions
41  *-----------------------------------------------------------------------------*/
42 /**
43  * API (Interface for TEECAPI) implementation for connecting to
44  * the Simulator daemon through socket
45  * @return socket file descriptor to connected server
46  */
47 int32_t connecttoServer(void) {
48         LOGD(MODULE_SSF_LIB, "Entry");
49         int serverSocket, socklen;
50         size_t sock_path_len = 0;
51         struct sockaddr* sockptr;
52         struct sockaddr_un daemonsock;
53
54         if ((serverSocket = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
55                 LOGE(MODULE_SSF_LIB, "No socket for simdaemon");
56                 return -1;
57         }
58         daemonsock.sun_family = AF_UNIX;
59
60         sock_path_len = strlen(SIMDAEMON_SOCK_PATH);
61         strncpy(daemonsock.sun_path, SIMDAEMON_SOCK_PATH, sock_path_len+1);
62
63         socklen = sizeof(daemonsock);
64         sockptr = (struct sockaddr*)&daemonsock;
65         if (connect(serverSocket, sockptr, socklen) == -1) {
66                 LOGE(MODULE_SSF_LIB, "connection to simdaemon failed (s=%s)", SIMDAEMON_SOCK_PATH);
67                 close(serverSocket);
68                 return -1;
69         }
70         return serverSocket;
71 }
72
73 /**
74  * API (Interface for TEECAPI) implementation for disconnecting
75  * from the Simulator daemon through socket
76  * @param ServerSocket
77  */
78 void disconnectfromServer(int32_t serverSocket) {
79         int32_t result;
80         LOGD(MODULE_SSF_LIB, "Entry");
81         if (serverSocket > 0) {
82                 result = shutdown(serverSocket, SHUT_WR);
83                 if (result != 0) LOGE(MODULE_SSF_LIB, "disconnectfromServer failed");
84                 close(serverSocket);
85         } else {
86                 LOGE(MODULE_SSF_LIB, "Invalid socket, disconnectfromServer failed");
87         }
88 }
89
90 /**
91  * Function implementation for sending data to Simulator daemon
92  * through socket
93  * @param sockfd file descriptor
94  * @param fdata structured data to daemon
95  * @param size size of fdata in bytes
96  * @return
97  */
98 static uint32_t sendCommandtoDaemon(int32_t sockfd, char* fdata, size_t size) {
99         LOGD(MODULE_SSF_LIB, "Entry");
100         ssize_t nwrite = 0;
101         size_t nbytes = 0;
102         if (sockfd >= 0) {
103                 while (nbytes < size) {
104                         nwrite = send(sockfd, fdata + nbytes, size - nbytes, 0);
105                         if (nwrite == -1 && errno == EINTR)
106                                 continue;
107                         if (nwrite <= 0)
108                                 break;
109                         nbytes += nwrite;
110                 }
111                 return (size != nbytes) ? errno : 0;
112         }
113         LOGE(MODULE_SSF_LIB, "failed");
114         return TEEC_ERROR_COMMUNICATION;
115 }
116
117 /**
118  * Function implementation for recieving data from Simulator
119  * daemon through socket
120  * @param sockfd file descriptor
121  * @param fdata structured data to be received
122  * @param size size of fdata in bytes
123  * @return
124  */
125 static uint32_t receiveResponse(int32_t sockfd, char* fdata, size_t size) {
126         LOGD(MODULE_SSF_LIB, "Entry");
127         ssize_t nread = 0;
128         size_t nbytes = 0;
129         if (sockfd >= 0) {
130                 while (nbytes < size) {
131                         nread = recv(sockfd, fdata + nbytes, size - nbytes, 0);
132                         if (nread == -1 && errno == EINTR)
133                                 continue;
134                         if (nread <= 0)
135                                 break;
136                         nbytes += nread;
137                 }
138                 return (size != nbytes) ? errno : 0;
139         }
140         LOGE(MODULE_SSF_LIB, "failed");
141         return TEEC_ERROR_COMMUNICATION;
142 }
143
144 /**
145  * Test function to test the daemon
146  * @param cmd
147  * @param fdata
148  * @param size
149  * @param in
150  * @return
151  */
152 #ifdef TEST
153 static uint32_t Test(char cmd, char* fdata, size_t size, uint32_t in) {
154         //TODO: Implementation
155         return TEE_SUCCESS;
156 }
157 #endif
158
159 /**
160  * API (Interface for TEECAPI) implementation for sending a
161  * command to Simulator daemon
162  * @param sockfd file descriptor
163  * @param cmd command to simulator daemon
164  * @param data structured data to daemon
165  * @param size size of data
166  * @return
167  */
168 uint32_t sendCommand(int32_t sockfd, TEE_CMD cmd, void* data, size_t size) {
169         LOGD(MODULE_SSF_LIB, "Entry");
170         TEE_Result result = TEE_SUCCESS;
171         char command = (char)cmd;
172 #ifdef TEST
173         result = Test(command, (char*)data, size, 1);
174         if (result != TEE_SUCCESS) {
175                 return TEE_ERROR_GENERIC;
176         }
177 #endif
178         result = sendCommandtoDaemon(sockfd, (char*)&command, sizeof(char));
179         if (result != TEE_SUCCESS) {
180                 return TEE_ERROR_GENERIC;
181         }
182         result = sendCommandtoDaemon(sockfd, (char*)data, size);
183         if (result != TEE_SUCCESS) {
184                 return TEE_ERROR_GENERIC;
185         }
186         result = receiveResponse(sockfd, (char*)&command, sizeof(char));
187         if (result != TEE_SUCCESS) {
188                 return TEE_ERROR_GENERIC;
189         }
190         result = receiveResponse(sockfd, (char*)data, size);
191         if (result != TEE_SUCCESS) {
192                 return TEE_ERROR_GENERIC;
193         }
194 #ifdef TEST
195         result = Test(command, (char*)data, size, 0);
196         if (result != TEE_SUCCESS) {
197                 return TEE_ERROR_GENERIC;
198         }
199 #endif
200         return result;
201 }