예제 #1
0
        protected byte[] EncryptSinglecastCommandInternal(SinglecastKey sckey, SpanTable spanTable, byte senderNodeId, byte receiverNodeId, byte[] homeId, byte[] plainData, Extensions extentions, SubstituteSettings substituteSettings)
        {
            Extensions          ext        = extentions ?? new Extensions();
            InvariantPeerNodeId peerNodeId = new InvariantPeerNodeId(senderNodeId, receiverNodeId);
            var spanContainer = spanTable.GetContainer(peerNodeId);
            var spanExtension = GetPersonalizationArray(sckey, spanContainer);

            if (spanExtension != null)
            {
                ext.AddSpanExtension(spanExtension);
            }
            spanContainer.NextNonce();
            spanTable.UpdateTxSequenceNumber(peerNodeId);

            var iv             = GetPropertyIV(spanContainer.Span);
            var sequenceNumber = GetPropertySequenceNo(spanContainer.TxSequenceNumber);
            var reserved       = GetPropertyReserved(0);

            FillExtensions(ext, true);
            byte[] encryptedData = EncryptS2(sckey.CcmKey,
                                             sequenceNumber,
                                             plainData,
                                             senderNodeId,
                                             receiverNodeId,
                                             homeId,
                                             iv,
                                             reserved,
                                             ext);
            if (plainData != null && encryptedData != null)
            {
                SaveDataForRetransmission(peerNodeId, plainData, substituteSettings, sckey.SecurityScheme);
            }
            return(encryptedData);
        }
예제 #2
0
        public byte[] GenerateNonceReport(SpanTable spanTable, InvariantPeerNodeId peerNodeId, byte txSequenceNumber, byte rxSequenceNumber,
                                          bool isSos, bool isMos)
        {
            byte[] receiverNonce = GetRandomData();
            if (isSos)
            {
                if (spanTable.CheckNonceExists(peerNodeId))
                {
                    spanTable.SetNonceFree(peerNodeId);
                }
                spanTable.Add(peerNodeId, receiverNonce, txSequenceNumber, rxSequenceNumber);
            }
            var nonceReportCmd = new COMMAND_CLASS_SECURITY_2.SECURITY_2_NONCE_REPORT
            {
                sequenceNumber = txSequenceNumber,
                properties1    = new COMMAND_CLASS_SECURITY_2.SECURITY_2_NONCE_REPORT.Tproperties1
                {
                    sos = (byte)(isSos ? 1 : 0),
                    mos = (byte)(isMos ? 1 : 0)
                },
                receiversEntropyInput = receiverNonce
            };

            return(nonceReportCmd);
        }
예제 #3
0
 public bool CheckNonceExists(InvariantPeerNodeId peerNodeId)
 {
     lock (_synchObject)
     {
         return(_table.ContainsKey(peerNodeId) && _table[peerNodeId].SpanState != SpanStates.None);
     }
 }
예제 #4
0
 public SpanStates GetSpanState(InvariantPeerNodeId peerNodeId)
 {
     lock (_synchObject)
     {
         if (_table.ContainsKey(peerNodeId) && _table[peerNodeId].SpanState != SpanStates.None)
         {
             return(_table[peerNodeId].SpanState);
         }
         return(SpanStates.None);
     }
 }
예제 #5
0
        public static byte[] EncryptPayload(byte senderId, byte receiverId, byte[] homeId, byte sequenceNumber, byte[] receiverNonce,
                                            byte[] senderNonce, byte[] networkKey, byte[] textToEncrypt, int generationCount, bool isRealKey)
        {
            var ret = new COMMAND_CLASS_SECURITY_2.SECURITY_2_MESSAGE_ENCAPSULATION {
                sequenceNumber = sequenceNumber
            };
            InvariantPeerNodeId peerNodeId = new InvariantPeerNodeId(0);
            var mpanKey         = new byte[SecurityS2Utils.KEY_SIZE];
            var ccmKey          = new byte[SecurityS2Utils.KEY_SIZE];
            var personalization = new byte[SecurityS2Utils.PERSONALIZATION_SIZE];

            if (isRealKey)
            {
                SecurityS2Utils.NetworkKeyExpand(networkKey, ccmKey, personalization, mpanKey);
            }
            else
            {
                SecurityS2Utils.TempKeyExpand(networkKey, ccmKey, personalization, mpanKey);
            }
            SpanTable spanTable = new SpanTable();

            spanTable.Add(peerNodeId, receiverNonce, 0, 0);
            SpanContainer spanContainer = spanTable.GetContainer(peerNodeId);

            spanContainer.InstantiateWithSenderNonce(senderNonce, personalization);
            for (int i = 0; i < generationCount; i++)
            {
                spanContainer.NextNonce();
            }

            AAD aad = new AAD
            {
                SenderNodeId   = senderId,
                ReceiverNodeId = receiverId,
                HomeId         = homeId,
                PayloadLength  = (ushort)(textToEncrypt.Length + SecurityS2Utils.AUTH_DATA_HEADER_LENGTH),
                SequenceNumber = sequenceNumber
            };

            aad.PayloadLength += (ushort)((byte[])ret).Length;
            var cipherData = SecurityS2Utils.CcmEncryptAndAuth(ccmKey, spanContainer.Span, aad, textToEncrypt);

            if (cipherData != null && cipherData.Length > 0)
            {
                ret.ccmCiphertextObject = new List <byte>(cipherData);
            }
            else
            {
                ret = null;
            }
            return(ret);
        }
예제 #6
0
        //public void UpdateRxSequenceNumber(InvariantPeerNodeId peerNodeId, byte rxSequenceNumber)
        //{
        //    lock (_synchObject)
        //    {
        //        if (_table.ContainsKey(peerNodeId))
        //        {
        //            _table[peerNodeId].RxSequenceNumber = rxSequenceNumber;
        //        }
        //    }
        //}

        public byte GetRxSequenceNumber(InvariantPeerNodeId peerNodeId)
        {
            byte ret = 0;

            lock (_synchObject)
            {
                if (_table.ContainsKey(peerNodeId))
                {
                    ret = _table[peerNodeId].RxSequenceNumber;
                }
            }
            return(ret);
        }
예제 #7
0
        public bool SetNonceFree(InvariantPeerNodeId peerNodeId)
        {
            bool ret = false;

            lock (_synchObject)
            {
                if (_table.ContainsKey(peerNodeId))
                {
                    ret = true;
                    _table[peerNodeId].SetNonceFree();
                }
            }
            return(ret);
        }
예제 #8
0
 private void BackupTxSequenceNumber(InvariantPeerNodeId peerNodeId)
 {
     if (_table.ContainsKey(peerNodeId))
     {
         if (_txSequenceNumberTable.ContainsKey(peerNodeId))
         {
             _txSequenceNumberTable[peerNodeId] = _table[peerNodeId].TxSequenceNumber;
         }
         else
         {
             _txSequenceNumberTable.Add(peerNodeId, _table[peerNodeId].TxSequenceNumber);
         }
     }
 }
예제 #9
0
        public byte[] EncryptSinglecastCommand(SinglecastKey sckey, SpanTable spanTable, byte senderNodeId, byte receiverNodeId, byte[] homeId, byte[] plainData, Extensions extentions, SubstituteSettings substituteSettings)
        {
            byte[] encryptedData           = null;
            InvariantPeerNodeId peerNodeId = new InvariantPeerNodeId(senderNodeId, receiverNodeId);
            var spanContainer = spanTable.GetContainer(peerNodeId);

            if (spanContainer != null)
            {
                encryptedData = EncryptSinglecastCommandInternal(sckey, spanTable, senderNodeId, receiverNodeId, homeId, plainData, extentions, substituteSettings);
            }
            else
            {
            }
            return(encryptedData);
        }
예제 #10
0
        public byte UpdateTxSequenceNumber(InvariantPeerNodeId peerNodeId)
        {
            byte ret = 0;

            lock (_synchObject)
            {
                if (_table.ContainsKey(peerNodeId))
                {
                    _table[peerNodeId].TxSequenceNumber++;
                    ret = _table[peerNodeId].TxSequenceNumber;
                }
                BackupTxSequenceNumber(peerNodeId);
            }
            return(ret);
        }
예제 #11
0
 /// <summary>
 /// Remove if exists and adds new nonce with Receiver state to table.
 /// </summary>
 /// <param name="peerNodeId">Sender node id</param>
 /// <param name="receiverNonce">16 bytes receiver nonce</param>
 public void AddOrReplace(InvariantPeerNodeId peerNodeId, byte[] receiverNonce, byte txSequenceNumber, byte rxSequenceNumber)
 {
     lock (_synchObject)
     {
         if (_table.ContainsKey(peerNodeId))
         {
             _table[peerNodeId].SetReceiversNonceState(receiverNonce);
             _table[peerNodeId].RxSequenceNumber = rxSequenceNumber;
         }
         else
         {
             _table.Add(peerNodeId, new SpanContainer(receiverNonce, txSequenceNumber, rxSequenceNumber));
         }
         BackupTxSequenceNumber(peerNodeId);
     }
 }
예제 #12
0
        public bool IsValidRxSequenceNumber(InvariantPeerNodeId peerNodeId, byte rxSequenceNumber)
        {
            bool ret = false;

            lock (_synchObject)
            {
                if (_table.ContainsKey(peerNodeId))
                {
                    ret = _table[peerNodeId].RxSequenceNumber != rxSequenceNumber;
                }
                else
                {
                    ret = true;
                }
            }
            return(ret);
        }
예제 #13
0
        public byte GetTxSequenceNumber(InvariantPeerNodeId peerNodeId)
        {
            byte ret = 0;

            lock (_synchObject)
            {
                if (_table.ContainsKey(peerNodeId))
                {
                    ret = _table[peerNodeId].TxSequenceNumber;
                }
                else if (_txSequenceNumberTable.ContainsKey(peerNodeId))
                {
                    ret = ++_txSequenceNumberTable[peerNodeId];
                }
                else
                {
                    ret = 0x55;
                    _txSequenceNumberTable.Add(peerNodeId, ret);
                }
            }
            return(ret);
        }
예제 #14
0
        /// <summary>
        /// Adds new nonce with Receiver state to table
        /// </summary>
        /// <param name="peerNodeId">Sender node id</param>
        /// <param name="receiverNonce">16 bytes receiver nonce</param>
        /// <param name="sequenceNumber">Sequence number</param>
        public void Add(InvariantPeerNodeId peerNodeId, byte[] receiverNonce, byte txSequenceNumber, byte rxSequenceNumber)
        {
            lock (_synchObject)
            {
                if (!_table.ContainsKey(peerNodeId))
                {
                    _table.Add(peerNodeId, new SpanContainer(receiverNonce, txSequenceNumber, rxSequenceNumber));
                }
                else if (_table.ContainsKey(peerNodeId) && _table[peerNodeId].SpanState == SpanStates.None)
                {
                    _table[peerNodeId].SetReceiversNonceState(receiverNonce);
                    _table[peerNodeId].TxSequenceNumber = txSequenceNumber;
                    _table[peerNodeId].RxSequenceNumber = rxSequenceNumber;
                }
                else
                {
                    throw new InvalidOperationException("Nonce with specified peerNodeId already exists");
                }

                BackupTxSequenceNumber(peerNodeId);
            }
        }
예제 #15
0
 protected virtual void SaveDataForRetransmission(InvariantPeerNodeId peerNodeId, byte[] plainData, SubstituteSettings substituteSettings, SecuritySchemes scheme)
 {
 }
예제 #16
0
        public static bool DecryptSinglecastFrame(
            SpanContainer spanContainer,
            SinglecastKey singlecastKey,
            byte sourceNodeId,
            byte destNodeId,
            byte[] homeId,
            COMMAND_CLASS_SECURITY_2.SECURITY_2_MESSAGE_ENCAPSULATION cmd,
            out byte[] data,
            out Extensions extensions)
        {
            List <COMMAND_CLASS_SECURITY_2.SECURITY_2_MESSAGE_ENCAPSULATION.TVG1> encryptedExtensionsList = new List <COMMAND_CLASS_SECURITY_2.SECURITY_2_MESSAGE_ENCAPSULATION.TVG1>();
            List <COMMAND_CLASS_SECURITY_2.SECURITY_2_MESSAGE_ENCAPSULATION.TVG1> extensionsList          = new List <COMMAND_CLASS_SECURITY_2.SECURITY_2_MESSAGE_ENCAPSULATION.TVG1>();

            extensions = null;
            data       = null;
            bool ret = false;
            bool isDecryptSucceeded        = false;
            InvariantPeerNodeId peerNodeId = new InvariantPeerNodeId(destNodeId, sourceNodeId);

            extensionsList = cmd.vg1;
            if (spanContainer != null && singlecastKey != null)
            {
                spanContainer.RxSequenceNumber = cmd.sequenceNumber;
                if (spanContainer.SpanState == SpanStates.ReceiversNonce)
                {
                    #region SpanStates.ReceiversNonce
                    // Establish nonce synchronization.
                    byte[] senderEntropyInput = null;
                    if (cmd.properties1.extension == 1)
                    {
                        foreach (var extData in cmd.vg1)
                        {
                            if (extData.properties1.type == (byte)ExtensionTypes.Span &&
                                extData.extensionLength == 18 &&
                                extData.extension.Count == 16)
                            {
                                senderEntropyInput = extData.extension.ToArray();
                                break;
                            }
                        }
                    }

                    if (senderEntropyInput != null)
                    {
                        var receiverEntropyInput = spanContainer.ReceiversNonce;
                        spanContainer.InstantiateWithSenderNonce(senderEntropyInput, singlecastKey.Personalization);
                        byte[] plainData;
                        spanContainer.NextNonce();
                        isDecryptSucceeded = DecryptS2(singlecastKey.CcmKey,
                                                       spanContainer.Span,
                                                       sourceNodeId,
                                                       destNodeId,
                                                       homeId,
                                                       cmd,
                                                       out plainData,
                                                       out encryptedExtensionsList);
                        if (isDecryptSucceeded)
                        {
                            extensions = new Extensions
                            {
                                ExtensionsList          = extensionsList ?? new List <COMMAND_CLASS_SECURITY_2.SECURITY_2_MESSAGE_ENCAPSULATION.TVG1>(),
                                EncryptedExtensionsList = encryptedExtensionsList ?? new List <COMMAND_CLASS_SECURITY_2.SECURITY_2_MESSAGE_ENCAPSULATION.TVG1>()
                            };
                            ret  = true;
                            data = plainData;
                        }
                        else
                        {
                            extensions = new Extensions
                            {
                                ExtensionsList          = extensionsList ?? new List <COMMAND_CLASS_SECURITY_2.SECURITY_2_MESSAGE_ENCAPSULATION.TVG1>(),
                                EncryptedExtensionsList = new List <COMMAND_CLASS_SECURITY_2.SECURITY_2_MESSAGE_ENCAPSULATION.TVG1>()
                            };
                            spanContainer.SetReceiversNonceState();
                        }
                    }

                    #endregion
                }
                else if (spanContainer.SpanState == SpanStates.Span)
                {
                    #region SpanStates.Span
                    // Check nonce synchronization.
                    int    attemptsCount = 5;
                    byte[] plainData     = null;
                    while (!isDecryptSucceeded && attemptsCount > 0)
                    {
                        spanContainer.NextNonce();
                        attemptsCount--;
                        if (spanContainer != null)
                        {
                            isDecryptSucceeded = DecryptS2(singlecastKey.CcmKey,
                                                           spanContainer.Span,
                                                           sourceNodeId,
                                                           destNodeId,
                                                           homeId,
                                                           cmd,
                                                           out plainData,
                                                           out encryptedExtensionsList);
                        }
                    }
                    if (isDecryptSucceeded)
                    {
                        extensions = new Extensions
                        {
                            ExtensionsList          = extensionsList ?? new List <COMMAND_CLASS_SECURITY_2.SECURITY_2_MESSAGE_ENCAPSULATION.TVG1>(),
                            EncryptedExtensionsList = encryptedExtensionsList ?? new List <COMMAND_CLASS_SECURITY_2.SECURITY_2_MESSAGE_ENCAPSULATION.TVG1>()
                        };
                        ret  = true;
                        data = plainData;
                    }
                    #endregion
                }
                else
                {
                    throw new InvalidOperationException("Unexpected nonce state");
                }
            }
            return(ret);
        }
예제 #17
0
        public static byte[] DecryptPayload(byte senderId, byte receiverId, byte[] homeId, byte sequenceNumber, byte[] receiverNonce,
                                            byte[] senderNonce, byte[] networkKey, int generationCount, bool isRealKey, byte[] fullMessageS2, out int currentGenerationCount)
        {
            byte[] ret = null;
            currentGenerationCount = 0;
            if (fullMessageS2 != null && fullMessageS2.Length > 2)
            {
                var msgEncap = (COMMAND_CLASS_SECURITY_2.SECURITY_2_MESSAGE_ENCAPSULATION)fullMessageS2;

                var peerNodeId      = new InvariantPeerNodeId(0);
                var mpanKey         = new byte[SecurityS2Utils.KEY_SIZE];
                var ccmKey          = new byte[SecurityS2Utils.KEY_SIZE];
                var personalization = new byte[SecurityS2Utils.PERSONALIZATION_SIZE];
                if (isRealKey)
                {
                    SecurityS2Utils.NetworkKeyExpand(networkKey, ccmKey, personalization, mpanKey);
                }
                else
                {
                    SecurityS2Utils.TempKeyExpand(networkKey, ccmKey, personalization, mpanKey);
                }
                SpanTable spanTable = new SpanTable();
                spanTable.Add(peerNodeId, receiverNonce, 0, 0);
                SpanContainer spanContainer = spanTable.GetContainer(peerNodeId);
                spanContainer.InstantiateWithSenderNonce(senderNonce, personalization);


                var messageLength = (ushort)fullMessageS2.Length;
                AAD aad           = new AAD
                {
                    SenderNodeId   = senderId,
                    ReceiverNodeId = receiverId,
                    HomeId         = homeId,
                    PayloadLength  = messageLength,
                    SequenceNumber = sequenceNumber,
                    StatusByte     = msgEncap.properties1
                };
                if (msgEncap.properties1.extension == 1)
                {
                    var dataList = new List <byte>();
                    foreach (var vg1 in msgEncap.vg1)
                    {
                        dataList.AddRange(new byte[] { vg1.extensionLength, vg1.properties1 });
                        dataList.AddRange(vg1.extension);
                    }
                    aad.ExtensionData = dataList.ToArray();
                }

                for (int i = 0; i < generationCount; i++)
                {
                    spanContainer.NextNonce();
                    ret = SecurityS2Utils.CcmDecryptAndAuth(ccmKey, spanContainer.Span, aad, msgEncap.ccmCiphertextObject.ToArray());
                    if (ret != null && ret.Length > 0)
                    {
                        currentGenerationCount = i + 1;
                        break;
                    }
                }
            }
            return(ret);
        }