1 /*
2 **
3 ** Copyright 2020, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 ** http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17 #include "SocketTransport.h"
18
19 #include <arpa/inet.h>
20 #include <errno.h>
21 #include <sys/socket.h>
22 #include <memory>
23 #include <vector>
24
25 #include <android-base/logging.h>
26
27 #include "ITransport.h"
28
29 #define PORT 8080
30 #define IPADDR "192.168.9.112"
31 #define MAX_RECV_BUFFER_SIZE 2500
32
33 namespace keymint::javacard {
34 using std::shared_ptr;
35 using std::vector;
36
openConnection()37 bool SocketTransport::openConnection() {
38 struct sockaddr_in serv_addr;
39 if ((mSocket = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
40 LOG(ERROR) << "Socket creation failed"
41 << " Error: " << strerror(errno);
42 return false;
43 }
44
45 serv_addr.sin_family = AF_INET;
46 serv_addr.sin_port = htons(PORT);
47
48 // Convert IPv4 and IPv6 addresses from text to binary form
49 if (inet_pton(AF_INET, IPADDR, &serv_addr.sin_addr) <= 0) {
50 LOG(ERROR) << "Invalid address/ Address not supported.";
51 return false;
52 }
53
54 if (connect(mSocket, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
55 close(mSocket);
56 LOG(ERROR) << "Connection failed. Error: " << strerror(errno);
57 return false;
58 }
59 socketStatus = true;
60 return true;
61 }
62
sendData(const vector<uint8_t> & inData,vector<uint8_t> & output)63 bool SocketTransport::sendData(const vector<uint8_t>& inData, vector<uint8_t>& output) {
64 int count = 1;
65 while (!socketStatus && count++ < 5) {
66 sleep(1);
67 LOG(ERROR) << "Trying to open socket connection... count: " << count;
68 openConnection();
69 }
70
71 if (count >= 5) {
72 LOG(ERROR) << "Failed to open socket connection";
73 return false;
74 }
75 // Prepend the input length to the inputData before sending.
76 vector<uint8_t> inDataPrependedLength;
77 inDataPrependedLength.push_back(static_cast<uint8_t>(inData.size() >> 8));
78 inDataPrependedLength.push_back(static_cast<uint8_t>(inData.size() & 0xFF));
79 inDataPrependedLength.insert(inDataPrependedLength.end(), inData.begin(), inData.end());
80
81 if (0 >
82 send(mSocket, inDataPrependedLength.data(), inDataPrependedLength.size(), MSG_NOSIGNAL)) {
83 static int connectionResetCnt = 0; /* To avoid loop */
84 if ((ECONNRESET == errno || EPIPE == errno) && connectionResetCnt == 0) {
85 // Connection reset. Try open socket and then sendData.
86 socketStatus = false;
87 connectionResetCnt++;
88 return sendData(inData, output);
89 }
90 LOG(ERROR) << "Failed to send data over socket err: " << errno;
91 connectionResetCnt = 0;
92 return false;
93 }
94
95 return readData(output);
96 }
97
closeConnection()98 bool SocketTransport::closeConnection() {
99 close(mSocket);
100 socketStatus = false;
101 return true;
102 }
103
isConnected()104 bool SocketTransport::isConnected() {
105 return socketStatus;
106 }
107
readData(vector<uint8_t> & output)108 bool SocketTransport::readData(vector<uint8_t>& output) {
109 uint8_t buffer[MAX_RECV_BUFFER_SIZE];
110 ssize_t expectedResponseLen = 0;
111 ssize_t totalBytesRead = 0;
112 // The first 2 bytes in the response contains the expected response length.
113 do {
114 size_t i = 0;
115 ssize_t numBytes = read(mSocket, buffer, MAX_RECV_BUFFER_SIZE);
116 if (0 > numBytes) {
117 LOG(ERROR) << "Failed to read data from socket.";
118 return false;
119 }
120 totalBytesRead += numBytes;
121 if (expectedResponseLen == 0) {
122 // First two bytes in the response contains the expected response length.
123 expectedResponseLen |= static_cast<ssize_t>(buffer[1] & 0xFF);
124 expectedResponseLen |= static_cast<ssize_t>((buffer[0] << 8) & 0xFF00);
125 // 2 bytes for storing the length.
126 expectedResponseLen += 2;
127 i = 2;
128 }
129 for (; i < numBytes; i++) {
130 output.push_back(buffer[i]);
131 }
132 } while(totalBytesRead < expectedResponseLen);
133
134 return true;
135 }
136
137 } // namespace keymint::javacard
138