Skip to content

Commit bbf807d

Browse files
committed
Fix sending encrypted packets
Fixes both multiframe and single frame where single frame was actually over TLS max data size
1 parent c480dd4 commit bbf807d

1 file changed

Lines changed: 64 additions & 39 deletions

File tree

base/src/main/java/com/smartdevicelink/protocol/SdlProtocolBase.java

Lines changed: 64 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,10 @@ public class SdlProtocolBase {
7171
private final static String FailurePropagating_Msg = "Failure propagating ";
7272

7373
private static final int TLS_MAX_RECORD_SIZE = 16384;
74+
private final static int TLS_RECORD_HEADER_SIZE = 5;
75+
private final static int TLS_RECORD_MES_AUTH_CDE_SIZE = 32;
76+
private final static int TLS_MAX_RECORD_PADDING_SIZE = 256;
77+
private final static int TLS_MAX_DATA_TO_ENCRYPT_SIZE = TLS_MAX_RECORD_SIZE - TLS_RECORD_HEADER_SIZE - TLS_RECORD_MES_AUTH_CDE_SIZE - TLS_MAX_RECORD_PADDING_SIZE;
7478

7579
private static final int PRIMARY_TRANSPORT_ID = 1;
7680
private static final int SECONDARY_TRANSPORT_ID = 2;
@@ -561,7 +565,8 @@ public void endSession(byte sessionID) {
561565
public void sendMessage(ProtocolMessage protocolMsg) {
562566
SessionType sessionType = protocolMsg.getSessionType();
563567
byte sessionID = protocolMsg.getSessionID();
564-
568+
boolean requiresEncryption = protocolMsg.getPayloadProtected();
569+
SdlSecurityBase sdlSec = null;
565570
byte[] data;
566571
if (protocolVersion.getMajor() > 1 && sessionType != SessionType.NAV && sessionType != SessionType.PCM) {
567572
if (sessionType.eq(SessionType.CONTROL)) {
@@ -590,21 +595,15 @@ public void sendMessage(ProtocolMessage protocolMsg) {
590595
data = protocolMsg.getData();
591596
}
592597

593-
if (iSdlProtocol != null && protocolMsg.getPayloadProtected()) {
594-
595-
if (data != null && data.length > 0) {
596-
byte[] dataToRead = new byte[TLS_MAX_RECORD_SIZE];
597-
SdlSecurityBase sdlSec = iSdlProtocol.getSdlSecurity();
598-
if (sdlSec == null)
599-
return;
600-
601-
Integer iNumBytes = sdlSec.encryptData(data, dataToRead);
602-
if ((iNumBytes == null) || (iNumBytes <= 0))
603-
return;
604-
605-
byte[] encryptedData = new byte[iNumBytes];
606-
System.arraycopy(dataToRead, 0, encryptedData, 0, iNumBytes);
607-
data = encryptedData;
598+
if (requiresEncryption) {
599+
if (iSdlProtocol == null) {
600+
DebugTool.logError(TAG, "Unable to encrypt packet, protocol callback was null");
601+
return;
602+
}
603+
sdlSec = iSdlProtocol.getSdlSecurity();
604+
if (sdlSec == null) {
605+
DebugTool.logError(TAG, "Unable to encrypt packet, security library not found");
606+
return;
608607
}
609608
}
610609

@@ -616,24 +615,25 @@ public void sendMessage(ProtocolMessage protocolMsg) {
616615
return;
617616
}
618617

619-
synchronized (messageLock) {
620-
if (data != null && data.length > getMtu(sessionType)) {
618+
//Set the MTU according to session MTU provided by the IVI or the max data size for encryption if required
619+
final Long mtu = requiresEncryption ? TLS_MAX_DATA_TO_ENCRYPT_SIZE : getMtu(sessionType);
621620

621+
synchronized (messageLock) {
622+
if (data != null && data.length > mtu) {
623+
//Since the packet is larger than the mtu size, it will be sent as a multi-frame packet
622624
messageID++;
623625

624626
// Assemble first frame.
625-
Long mtu = getMtu(sessionType);
626-
int frameCount = Long.valueOf(data.length / mtu).intValue();
627-
if (data.length % mtu > 0) {
628-
frameCount++;
629-
}
627+
int frameCount = (int) Math.ceil(data.length / (double) mtu);
628+
630629
byte[] firstFrameData = new byte[8];
631630
// First four bytes are data size.
632631
System.arraycopy(BitConverter.intToByteArray(data.length), 0, firstFrameData, 0, 4);
633632
// Second four bytes are frame count.
634633
System.arraycopy(BitConverter.intToByteArray(frameCount), 0, firstFrameData, 4, 4);
635634

636-
SdlPacket firstHeader = SdlPacketFactory.createMultiSendDataFirst(sessionType, sessionID, messageID, (byte) protocolVersion.getMajor(), firstFrameData, protocolMsg.getPayloadProtected());
635+
//NOTE: First frames cannot be encrypted because their payloads need to be exactly 8 bytes
636+
SdlPacket firstHeader = SdlPacketFactory.createMultiSendDataFirst(sessionType, sessionID, messageID, (byte) protocolVersion.getMajor(), firstFrameData, false);
637637
firstHeader.setPriorityCoefficient(1 + protocolMsg.priorityCoefficient);
638638
firstHeader.setTransportRecord(activeTransports.get(sessionType));
639639
//Send the first frame
@@ -642,33 +642,58 @@ public void sendMessage(ProtocolMessage protocolMsg) {
642642
int currentOffset = 0;
643643
byte frameSequenceNumber = 0;
644644

645+
byte[] dataBuffer, encryptedData;
645646
for (int i = 0; i < frameCount; i++) {
646-
if (i < (frameCount - 1)) {
647-
++frameSequenceNumber;
648-
if (frameSequenceNumber ==
649-
SdlPacket.FRAME_INFO_FINAL_CONNESCUTIVE_FRAME) {
650-
// we can't use 0x00 as frameSequenceNumber, because
651-
// it's reserved for the last frame
652-
++frameSequenceNumber;
653-
}
654-
} else {
647+
648+
frameSequenceNumber++;
649+
if (i == frameCount - 1) {
655650
frameSequenceNumber = SdlPacket.FRAME_INFO_FINAL_CONNESCUTIVE_FRAME;
656-
} // end-if
651+
}
657652

658653
int bytesToWrite = data.length - currentOffset;
659654
if (bytesToWrite > mtu) {
660655
bytesToWrite = mtu.intValue();
661656
}
662-
SdlPacket consecHeader = SdlPacketFactory.createMultiSendDataRest(sessionType, sessionID, bytesToWrite, frameSequenceNumber, messageID, (byte) protocolVersion.getMajor(), data, currentOffset, bytesToWrite, protocolMsg.getPayloadProtected());
663-
consecHeader.setTransportRecord(activeTransports.get(sessionType));
664-
consecHeader.setPriorityCoefficient(i + 2 + protocolMsg.priorityCoefficient);
665-
handlePacketToSend(consecHeader);
657+
658+
SdlPacket consecutiveFrame;
659+
if (requiresEncryption) {
660+
//Retrieve a chunk of the data into a temporary buffer to be encrypted
661+
dataBuffer = new byte[bytesToWrite];
662+
System.arraycopy(data, currentOffset, dataBuffer, 0, bytesToWrite);
663+
664+
encryptedData = new byte[TLS_MAX_RECORD_SIZE];
665+
Integer numberOfBytesEncrypted = sdlSec.encryptData(dataBuffer, encryptedData);
666+
if (numberOfBytesEncrypted == null || (numberOfBytesEncrypted <= 0)) {
667+
DebugTool.logError(TAG, "Unable to encrypt data");
668+
return;
669+
}
670+
671+
consecutiveFrame = SdlPacketFactory.createMultiSendDataRest(sessionType, sessionID, numberOfBytesEncrypted, frameSequenceNumber, messageID, (byte) protocolVersion.getMajor(), encryptedData, 0, numberOfBytesEncrypted, true);
672+
} else {
673+
consecutiveFrame = SdlPacketFactory.createMultiSendDataRest(sessionType, sessionID, bytesToWrite, frameSequenceNumber, messageID, (byte) protocolVersion.getMajor(), data, currentOffset, bytesToWrite, false);
674+
}
675+
676+
consecutiveFrame.setTransportRecord(activeTransports.get(sessionType));
677+
consecutiveFrame.setPriorityCoefficient(i + 2 + protocolMsg.priorityCoefficient);
678+
handlePacketToSend(consecutiveFrame);
666679
currentOffset += bytesToWrite;
667680
}
668681
} else {
669682
messageID++;
683+
if (requiresEncryption && data != null && data.length > 0) {
684+
//Encrypt the data before sending
685+
byte[] encryptedData = new byte[TLS_MAX_RECORD_SIZE];
686+
Integer numberOfBytesEncrypted = sdlSec.encryptData(data, encryptedData);
687+
if (numberOfBytesEncrypted == null || (numberOfBytesEncrypted <= 0)) {
688+
DebugTool.logError(TAG, "Unable to encrypt data");
689+
return;
690+
}
691+
//Put the encrypted bytes back into the data array
692+
data = new byte[numberOfBytesEncrypted];
693+
System.arraycopy(encryptedData, 0, data, 0, numberOfBytesEncrypted);
694+
}
670695
int dataLength = data != null ? data.length : 0;
671-
SdlPacket header = SdlPacketFactory.createSingleSendData(sessionType, sessionID, dataLength, messageID, (byte) protocolVersion.getMajor(), data, protocolMsg.getPayloadProtected());
696+
SdlPacket header = SdlPacketFactory.createSingleSendData(sessionType, sessionID, dataLength, messageID, (byte) protocolVersion.getMajor(), data, requiresEncryption);
672697
header.setPriorityCoefficient(protocolMsg.priorityCoefficient);
673698
header.setTransportRecord(activeTransports.get(sessionType));
674699
handlePacketToSend(header);

0 commit comments

Comments
 (0)