From e3472c76f9e0ba6e368b58a1d0e2f172a51dcff2 Mon Sep 17 00:00:00 2001 From: Subrahmanyaman Date: Mon, 4 Apr 2022 19:24:04 +0000 Subject: [PATCH 1/2] JCardSim: Added code for the unimplemented function to fix the rkp generatekey issue --- .../com/android/javacard/seprovider/KMJCardSimulator.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Applet/JCardSimProviderLib/src/com/android/javacard/seprovider/KMJCardSimulator.java b/Applet/JCardSimProviderLib/src/com/android/javacard/seprovider/KMJCardSimulator.java index f4ee2cac..31ca6519 100644 --- a/Applet/JCardSimProviderLib/src/com/android/javacard/seprovider/KMJCardSimulator.java +++ b/Applet/JCardSimProviderLib/src/com/android/javacard/seprovider/KMJCardSimulator.java @@ -609,9 +609,13 @@ public short hmacSign(byte[] keyBuf, short keyStart, short keyLength, byte[] dat } @Override - public short hmacSign(Object hmacKey, byte[] data, short dataStart, short dataLength, + public short hmacSign(Object key, byte[] data, short dataStart, short dataLength, byte[] signature, short signatureStart) { - return 0; + if(!(key instanceof KMHmacKey)) { + KMException.throwIt(KMError.INVALID_ARGUMENT); + } + KMHmacKey hmacKey = (KMHmacKey) key; + return hmacSign(hmacKey.getKey(), data, dataStart, dataLength, signature, signatureStart); } @Override From 2b1f5590d65674cdab1157878107767e0296d872 Mon Sep 17 00:00:00 2001 From: Subrahmanyaman Date: Mon, 4 Apr 2022 19:50:24 +0000 Subject: [PATCH 2/2] While testing using socket and JCProxy setup prepend the length of data to the actual data sent or received. This is to fix the issue when only a portin of data is received on the socket. This issue is observed in GoldFish emulator. --- HAL/SocketTransport.cpp | 47 +++++++++++++---- HAL/SocketTransport.h | 1 + ProvisioningTool/include/socket.h | 3 +- ProvisioningTool/src/socket.cpp | 39 +++++++++++--- .../android/javacard/jcproxy/JCProxyMain.java | 52 ++++++++++--------- .../javacard/jcproxy/JCardSimulator.java | 7 ++- 6 files changed, 105 insertions(+), 44 deletions(-) diff --git a/HAL/SocketTransport.cpp b/HAL/SocketTransport.cpp index 10ceab35..edb8e464 100644 --- a/HAL/SocketTransport.cpp +++ b/HAL/SocketTransport.cpp @@ -58,7 +58,6 @@ bool SocketTransport::openConnection() { } bool SocketTransport::sendData(const vector& inData, vector& output) { - uint8_t buffer[MAX_RECV_BUFFER_SIZE]; int count = 1; while (!socketStatus && count++ < 5) { sleep(1); @@ -70,8 +69,13 @@ bool SocketTransport::sendData(const vector& inData, vector& o LOG(ERROR) << "Failed to open socket connection"; return false; } + // Prepend the input length to the inputData before sending. + vector inDataPrependedLength; + inDataPrependedLength.push_back(static_cast(inData.size() >> 8)); + inDataPrependedLength.push_back(static_cast(inData.size() & 0xFF)); + inDataPrependedLength.insert(inDataPrependedLength.end(), inData.begin(), inData.end()); - if (0 > send(mSocket, inData.data(), inData.size(), 0)) { + if (0 > send(mSocket, inDataPrependedLength.data(), inDataPrependedLength.size(), 0)) { static int connectionResetCnt = 0; /* To avoid loop */ if (ECONNRESET == errno && connectionResetCnt == 0) { // Connection reset. Try open socket and then sendData. @@ -83,15 +87,7 @@ bool SocketTransport::sendData(const vector& inData, vector& o connectionResetCnt = 0; return false; } - - ssize_t valRead = read(mSocket, buffer, MAX_RECV_BUFFER_SIZE); - if (0 > valRead) { - LOG(ERROR) << "Failed to read data from socket."; - } - for (size_t i = 0; i < valRead; i++) { - output.push_back(buffer[i]); - } - return true; + return readData(output); } bool SocketTransport::closeConnection() { @@ -104,4 +100,33 @@ bool SocketTransport::isConnected() { return socketStatus; } +bool SocketTransport::readData(vector& output) { + uint8_t buffer[MAX_RECV_BUFFER_SIZE]; + ssize_t expectedResponseLen = 0; + ssize_t totalBytesRead = 0; + // The first 2 bytes in the response contains the expected response length. + do { + size_t i = 0; + ssize_t numBytes = read(mSocket, buffer, MAX_RECV_BUFFER_SIZE); + if (0 > numBytes) { + LOG(ERROR) << "Failed to read data from socket."; + return false; + } + totalBytesRead += numBytes; + if (expectedResponseLen == 0) { + // First two bytes in the response contains the expected response length. + expectedResponseLen |= static_cast(buffer[1] & 0xFF); + expectedResponseLen |= static_cast((buffer[0] << 8) & 0xFF00); + // 2 bytes for storing the length. + expectedResponseLen += 2; + i = 2; + } + for (; i < numBytes; i++) { + output.push_back(buffer[i]); + } + } while(totalBytesRead < expectedResponseLen); + + return true; +} + } // namespace keymint::javacard diff --git a/HAL/SocketTransport.h b/HAL/SocketTransport.h index 2eb134fd..097694d9 100644 --- a/HAL/SocketTransport.h +++ b/HAL/SocketTransport.h @@ -46,6 +46,7 @@ class SocketTransport : public ITransport { bool isConnected() override; private: + bool readData(vector& output); /** * Socket instance. */ diff --git a/ProvisioningTool/include/socket.h b/ProvisioningTool/include/socket.h index 8f47325a..0efaa278 100644 --- a/ProvisioningTool/include/socket.h +++ b/ProvisioningTool/include/socket.h @@ -44,10 +44,11 @@ class SocketTransport bool isConnected(); private: + bool readData(std::vector& output); SocketTransport() : mSocket(-1), socketStatus(false) {} /** * Socket instance. */ int mSocket; bool socketStatus; -}; \ No newline at end of file +}; diff --git a/ProvisioningTool/src/socket.cpp b/ProvisioningTool/src/socket.cpp index 137cab3b..1c6797d4 100644 --- a/ProvisioningTool/src/socket.cpp +++ b/ProvisioningTool/src/socket.cpp @@ -73,8 +73,13 @@ bool SocketTransport::sendData(const std::vector& inData, std::vector inDataPrependedLength; + inDataPrependedLength.push_back(static_cast(inData.size() >> 8)); + inDataPrependedLength.push_back(static_cast(inData.size() & 0xFF)); + inDataPrependedLength.insert(inDataPrependedLength.end(), inData.begin(), inData.end()); - if (0 > send(mSocket, inData.data(), inData.size(), 0)) { + if (0 > send(mSocket, inDataPrependedLength.data(), inDataPrependedLength.size(), 0)) { static int connectionResetCnt = 0; /* To avoid loop */ if (ECONNRESET == errno && connectionResetCnt == 0) { // Connection reset. Try open socket and then sendData. @@ -86,14 +91,35 @@ bool SocketTransport::sendData(const std::vector& inData, std::vector valRead) { +bool SocketTransport::readData(vector& output) { + uint8_t buffer[MAX_RECV_BUFFER_SIZE]; + ssize_t expectedResponseLen = 0; + ssize_t totalBytesRead = 0; + // The first 2 bytes in the response contains the expected response length. + do { + size_t i = 0; + ssize_t numBytes = read(mSocket, buffer, MAX_RECV_BUFFER_SIZE); + if (0 > numBytes) { std::cout << "Failed to read data from socket."; - } - for (ssize_t i = 0; i < valRead; i++) { + return false; + } + totalBytesRead += numBytes; + if (expectedResponseLen == 0) { + // First two bytes in the response contains the expected response length. + expectedResponseLen |= static_cast(buffer[1] & 0xFF); + expectedResponseLen |= static_cast((buffer[0] << 8) & 0xFF00); + // 2 bytes for storing the length. + expectedResponseLen += 2; + i = 2; + } + for (; i < numBytes; i++) { output.push_back(buffer[i]); - } + } + } while(totalBytesRead < expectedResponseLen); + return true; } @@ -106,4 +132,3 @@ bool SocketTransport::closeConnection() { bool SocketTransport::isConnected() { return socketStatus; } - diff --git a/TestingTools/JCProxy/src/com/android/javacard/jcproxy/JCProxyMain.java b/TestingTools/JCProxy/src/com/android/javacard/jcproxy/JCProxyMain.java index 90832b3f..84754aed 100644 --- a/TestingTools/JCProxy/src/com/android/javacard/jcproxy/JCProxyMain.java +++ b/TestingTools/JCProxy/src/com/android/javacard/jcproxy/JCProxyMain.java @@ -7,6 +7,7 @@ import java.util.Date; import com.sun.javacard.apduio.CadTransportException; +import javacard.framework.Util; /** * This program demonstrates a simple TCP/IP socket server. @@ -47,33 +48,36 @@ public static void main(String[] args) { byte[] inBytes = new byte[65536]; int readLen = 0, index = 0; - System.out.println("Socket input buffer size: " - + socket.getReceiveBufferSize()); + short totalLen = 0; + short totalReadLen = 0; + System.out.println("Socket input buffer size: " + socket.getReceiveBufferSize()); while ((readLen = isReader.read(inBytes, index, 1024 * 5)) > 0) { if (readLen > 0) { - System.out.println("Bytes read from index (" + index - + ") socket: " + readLen + " Estimate read: " - + isReader.available()); - byte[] outBytes; - - try { - outBytes = simulator.executeApdu( - Arrays.copyOfRange(inBytes, 0, index + readLen)); - outData = simulator.decodeDataOut(); - System.out.println( - "Return Data " + Utils.byteArrayToHexString(outData)); - byte[] finalOutData = new byte[outData.length - + outBytes.length]; - System.arraycopy(outData, 0, finalOutData, 0, outData.length); - System.arraycopy(outBytes, 0, finalOutData, outData.length, - outBytes.length); - output.write(finalOutData); - output.flush(); - index = 0; - } catch (IllegalArgumentException e) { - e.printStackTrace(); - index = readLen; + System.out.println("Bytes read from index (" + index + ") socket: " + readLen + " Estimate read: " + + isReader.available()); + if (totalLen == 0) { + // First two bytes holds the actual request length. + totalLen = Util.getShort(inBytes, (short) 0); + totalLen += 2; + } + totalReadLen += readLen; + if (totalReadLen < totalLen) { + // Read from the socket till all the bytes are read. + index += readLen; + continue; } + simulator.executeApdu(Arrays.copyOfRange(inBytes, (short) 2, totalReadLen)); + outData = simulator.decodeDataOut(); + + byte[] finalOutData = new byte[outData.length + 2]; + Util.setShort(finalOutData, (short) 0, (short) outData.length); + System.arraycopy(outData, 0, finalOutData, 2, outData.length); + output.write(finalOutData); + System.out.println("Return Data = " + Utils.byteArrayToHexString(finalOutData)); + output.flush(); + index = 0; + totalLen = 0; + totalReadLen = 0; } } } catch (IOException e) { diff --git a/TestingTools/JCProxy/src/com/android/javacard/jcproxy/JCardSimulator.java b/TestingTools/JCProxy/src/com/android/javacard/jcproxy/JCardSimulator.java index 7af495f3..981318bf 100644 --- a/TestingTools/JCProxy/src/com/android/javacard/jcproxy/JCardSimulator.java +++ b/TestingTools/JCProxy/src/com/android/javacard/jcproxy/JCardSimulator.java @@ -55,7 +55,12 @@ public byte[] executeApdu(byte[] apdu) throws Exception { @Override public byte[] decodeDataOut() { - return response.getData(); + byte[] resp = response.getData(); + byte[] status = intToByteArray(response.getSW()); + byte[] out = new byte[(resp.length + status.length)]; + System.arraycopy(resp, 0, out, 0, resp.length); + System.arraycopy(status, 0, out, resp.length, status.length); + return out; } }