@@ -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,65 @@ 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+
648+ frameSequenceNumber ++;
649+
650+ if (frameSequenceNumber == SdlPacket .FRAME_INFO_FINAL_CONNESCUTIVE_FRAME ) {
651+ //If sequence numbers roll over to 0, increment again to avoid
652+ //using the reserved sequence value for the final frame
647653 ++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 {
654+ }
655+
656+ if (i == frameCount - 1 ) {
655657 frameSequenceNumber = SdlPacket .FRAME_INFO_FINAL_CONNESCUTIVE_FRAME ;
656- } // end-if
658+ }
657659
658660 int bytesToWrite = data .length - currentOffset ;
659661 if (bytesToWrite > mtu ) {
660662 bytesToWrite = mtu .intValue ();
661663 }
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 );
664+
665+ SdlPacket consecutiveFrame ;
666+ if (requiresEncryption ) {
667+ //Retrieve a chunk of the data into a temporary buffer to be encrypted
668+ dataBuffer = new byte [bytesToWrite ];
669+ System .arraycopy (data , currentOffset , dataBuffer , 0 , bytesToWrite );
670+
671+ encryptedData = new byte [TLS_MAX_RECORD_SIZE ];
672+ Integer numberOfBytesEncrypted = sdlSec .encryptData (dataBuffer , encryptedData );
673+ if (numberOfBytesEncrypted == null || (numberOfBytesEncrypted <= 0 )) {
674+ DebugTool .logError (TAG , "Unable to encrypt data" );
675+ return ;
676+ }
677+
678+ consecutiveFrame = SdlPacketFactory .createMultiSendDataRest (sessionType , sessionID , numberOfBytesEncrypted , frameSequenceNumber , messageID , (byte ) protocolVersion .getMajor (), encryptedData , 0 , numberOfBytesEncrypted , true );
679+ } else {
680+ consecutiveFrame = SdlPacketFactory .createMultiSendDataRest (sessionType , sessionID , bytesToWrite , frameSequenceNumber , messageID , (byte ) protocolVersion .getMajor (), data , currentOffset , bytesToWrite , false );
681+ }
682+
683+ consecutiveFrame .setTransportRecord (activeTransports .get (sessionType ));
684+ consecutiveFrame .setPriorityCoefficient (i + 2 + protocolMsg .priorityCoefficient );
685+ handlePacketToSend (consecutiveFrame );
666686 currentOffset += bytesToWrite ;
667687 }
668688 } else {
669689 messageID ++;
690+ if (requiresEncryption && data != null && data .length > 0 ) {
691+ //Encrypt the data before sending
692+ byte [] encryptedData = new byte [TLS_MAX_RECORD_SIZE ];
693+ Integer numberOfBytesEncrypted = sdlSec .encryptData (data , encryptedData );
694+ if (numberOfBytesEncrypted == null || (numberOfBytesEncrypted <= 0 )) {
695+ DebugTool .logError (TAG , "Unable to encrypt data" );
696+ return ;
697+ }
698+ //Put the encrypted bytes back into the data array
699+ data = new byte [numberOfBytesEncrypted ];
700+ System .arraycopy (encryptedData , 0 , data , 0 , numberOfBytesEncrypted );
701+ }
670702 int dataLength = data != null ? data .length : 0 ;
671- SdlPacket header = SdlPacketFactory .createSingleSendData (sessionType , sessionID , dataLength , messageID , (byte ) protocolVersion .getMajor (), data , protocolMsg . getPayloadProtected () );
703+ SdlPacket header = SdlPacketFactory .createSingleSendData (sessionType , sessionID , dataLength , messageID , (byte ) protocolVersion .getMajor (), data , requiresEncryption );
672704 header .setPriorityCoefficient (protocolMsg .priorityCoefficient );
673705 header .setTransportRecord (activeTransports .get (sessionType ));
674706 handlePacketToSend (header );
@@ -1374,16 +1406,17 @@ protected void handleFrame(SdlPacket packet) {
13741406 if (packet .getPayload () != null && packet .getDataSize () > 0 && packet .isEncrypted ()) {
13751407
13761408 SdlSecurityBase sdlSec = iSdlProtocol .getSdlSecurity ();
1377- byte [] dataToRead = new byte [4096 ];
1409+ byte [] dataToRead = new byte [TLS_MAX_RECORD_SIZE ];
13781410
1379- Integer iNumBytes = sdlSec .decryptData (packet .getPayload (), dataToRead );
1380- if ((iNumBytes == null ) || (iNumBytes <= 0 )) {
1411+ Integer numberOfDecryptedBytes = sdlSec .decryptData (packet .getPayload (), dataToRead );
1412+ if ((numberOfDecryptedBytes == null ) || (numberOfDecryptedBytes <= 0 )) {
13811413 return ;
13821414 }
13831415
1384- byte [] decryptedData = new byte [iNumBytes ];
1385- System .arraycopy (dataToRead , 0 , decryptedData , 0 , iNumBytes );
1416+ byte [] decryptedData = new byte [numberOfDecryptedBytes ];
1417+ System .arraycopy (dataToRead , 0 , decryptedData , 0 , numberOfDecryptedBytes );
13861418 packet .payload = decryptedData ;
1419+ packet .dataSize = numberOfDecryptedBytes ;
13871420 }
13881421
13891422 if (packet .getFrameType ().equals (FrameType .Control )) {
0 commit comments